\chapter{Die Prelude}
\label{Sec:Prelude}

Consize ist eine sehr primitive Sprache, die allein mit rund 50 atomaren Wörter auskommt. Damit kann man zwar programmieren -- aber das Programmieren mit Consize einzig mit den Wörtern der VM ist zu umständlich und macht wenig Spaß. Viel schlimmer noch: Consize ist anfänglich nicht einmal in der Lage, mit Ihnen zu interagieren. Wenn Sie Consize starten, möchte Consize eine Datei namens \verb|prelude.txt| verarbeiten, die sogenannte Prelude. Fehlt die Datei oder steht dort Unsinn drin, macht Consize entweder gar nichts -- oder eben eine Menge Unsinn. So oder so, wir können mit Consize im Urzustand kaum sinnvoll arbeiten.

Der Clou an Consize ist: Die Sprache lässt sich erweitern. Machen wir uns die Sprache komfortabel. Wir werden etliche neue Wörter einführen, die hilfreiche Abstraktionen bieten, wir werden die Syntax erweitern und Consize interaktiv machen. Die dazu nötigen Programme stehen in der Prelude.
% Dieser Vorgang nennt sich "`\href{http://de.wikipedia.org/wiki/Bootstrapping_(Informatik)}{Bootstrapping}"'.

In diesem Kapitel sind alle Programmzeilen der Prelude durch ein vorangestelltes "`\verb|>> |"' (inkl.\ Leerzeichen) ausgezeichnet. Diese Markierung soll Ihnen helfen, in dem gesamten Text dieses Kapitels mit all seinen Erläuterungen und Beispielen die entscheidenden Programmzeilen zu identifizieren. Übrigens helfen die Markierungen auch Consize, um den Quelltext aus der Dokumentation zu filtern.
% Consize sucht sich die markierten Zeilen ebenfalls zusammen -- mehr dazu später in Kap.~\ref{Sec:Dateien}.
%Abseits zum Zwecke der Markierung können Sie die Auszeichnung "`\verb|>> |"' gedanklich ignorieren.

Auch wenn der Einstieg in die Prelude gleich ein unvermittelter Einstieg in die Programmierung mit Consize ist: Sie werden sehen, Consize ist nicht wirklich schwer zu verstehen. In Consize zerlegt man Programme systematisch in kleine Miniprogramme, die zu schreiben vergleichbar ist mit der Herausforderung von Rätselaufgaben. Und Sie haben einen immensen Vorteil bei der Arbeit mit Consize: Ihnen stehen die Consize-Erweiterungen direkt zur Verfügung. Sie arbeiten mit einer geladenen Prelude, um die Prelude zu verstehen. Das ist einfacher und umkomplizierter als sich das anhört. Sie können ein paar Hilfsmittel, wie z.B.\ den Debugger nutzen, um sich die Arbeitsweise von Consize zu veranschaulichen.

\section{Vorbereitungen: Was sein muss und was nützlich ist}

\subsection{Consize-Lizenz}

Die Prelude ist \href{http://de.wikipedia.org/wiki/Open_source}{Open-Source-Software} (OSS). Consize soll als Bildungsgut allen Interessierten frei zur Verfügung stehen.

\begin{verbatim}
>> %%% A Prelude for Consize in Consize
>> %%% Copyright (c) 2012, Dominikus Herzberg, Heilbronn University
>> %%% New BSD License: http://opensource.org/licenses/BSD-3-Clause
\end{verbatim}
%>> 

\subsection{Wie man Programme schreibt}
\label{Sec:LoadBootimage}

In Consize schreibt man keine Programme durch endlos lange Wort-Folgen -- damit bliebe ein entscheidender Mechanismus der Consize-VM ungenutzt. In Consize schreibt man Programme, indem man Wörter zum globalen Wörterbuch hinzufügt und das Wort mit einer Quotierung -- einem Mini-Programm, wenn man so möchte -- assoziiert. Das ist ein sehr einfacher, aber auch sehr leistungsfähiger Abstraktionsmechanismus. So abstrahiert das Wort \verb|-rot| die Quotierung \verb|[ rot rot ]|. Man spricht auch von einer benamten Abstraktion: \verb|-rot| ist der "`Name"' für die Abstraktion \verb|[ rot rot ]|. Sie erinnern sich an Kap.~\ref{Sec:AtomareWoerter}, S.~\pageref{rotsource}:

\begin{verbatim}
> \ -rot source
[ rot rot ]

\end{verbatim}

Mit dieser Abstraktionstechnik werden große und umfangreiche Programme überhaupt erst realisierbar. Wir Menschen müssen mehr oder minder große Programmeinheiten unter für uns sinngebenden Namen fassen können. Unsere intellektuellen Fähigkeiten stoßen beim Programmieren ansonsten rasch an ihre Grenzen.

Fortan wollen wir die Definition neuer Einträge im Wörterbuch wie folgt notieren: Ein Doppelpunkt \verb|:| leitet die Definition ein. Nach dem Doppelpunkt folgt das Wort, dann optional der Stapeleffekt und anschließend die das Wort definierende Wortfolge. Ein Semikolon schließt die Definition ab. Die definierende Wortfolge ist die mit dem Wort assoziierte Quotierung, allerdings ohne die eckigen Klammern.

In Anlehnung an die in Kap.~\ref{Sec:UrGrammatik} formulierte Grammatik hält die folgende Regel den Aufbau einer Wort-Definition fest.

\begin{grammar}
<definition> = ':' <separator> <word> [ <separator> <stackeffect> ] <separator> <program> <separator> ';'  
\end{grammar}

Die Angabe von Stapeleffekten kennen Sie bereits aus Kap.~\ref{Sec:ConsizeVM}. Alle Wörter der Consize-VM sind dort mit ihren Stapeleffekten angegeben worden. Details zur Umsetzung von \synt{definition} finden sich in Kap.~\ref{Sec:DefWords}, S.~\pageref{Sec:DefWords}.

Die Syntax zur Definition neuer Wörter kann nicht direkt verwendet werden, da die Consize-VM sie nicht kennt. Es bedarf eines kleinen Consize-Programms, das diese komfortable Art der Definition neuer Wörter zur Verfügung stellt. Dieses Consize-Programm ist als sogenanntes "`Bootimage"' in der Datei \verb|bootimage.txt| abgelegt und muss zuvor geladen werden. Der Ladevorgang fährt die Consize-VM in einen programmiertauglichen Zustand hoch, was man als "`\href{http://de.wikipedia.org/wiki/Booten}{Booten}"' bezeichnen kann.

%>> % A TINY BOOTIMAGE
%>> 
\begin{verbatim}
>> \ bootimage.txt slurp uncomment tokenize
>>   emptystack \ continue push \ concat push \ rot push
>>   \ top push \ swap push \ pop push \ dup push \ swap push
>>  call/cc
\end{verbatim}
%>> 

Der Code ist nichts anderes als eine ausführliche Variante von:

\begin{verbatim}
\ bootimage.txt load call
\end{verbatim}

Da die Wörter \verb|load| und \verb|call| zu Beginn der Abarbeitung der Prelude jedoch noch nicht bereit stehen, sind hier beide Wörter händisch aufgelöst worden. In Kap.~\ref{Sec:Bootstrapping} ist beschrieben, was in dem Bootimage steht und wie es erzeugt wird.

\subsection{Grundverhalten von \texttt{read-word} und \texttt{read-mapping}}

Der durch \verb|stepcc| beschriebene Ausführungsmechanismus der Consize-VM ist in engen Grenzen konfigurierbar. Das Verhalten der beiden Wörter \verb|read-word| und \verb|read-mapping| kann vom Anwender bzw. von der Anwenderin frei definiert werden, siehe Kap.~\ref{Sec:Continuations}.

Die Prelude assoziiert beide Wörter mit "`leeren"' Programmen. Das bedeutet: Wörter genauso wie Mappings werden einfach auf dem Datastack belassen.

%>> % DEFINITION OF META-WORDS
%>> 
\begin{verbatim}
>> : read-word    ( wrd -- wrd ) ;
>> : read-mapping ( map -- map ) ;
\end{verbatim}
%>> 

Durch Anpassung dieser Wörter sind beispielsweise Kodierungskonventionen für Wörter und Mappings einführbar, die eine Sonderbehandlung erfahren oder eine Vorverarbeitung erfordern sollen. Zu beachten ist, dass eine Neudefinition dieser Meta-Wörter kompatibel bleibt zum Standardverhalten. Sonst besteht das Risiko, existierenden Code in größerem Umfang zu brechen.

\subsection{Mehr davon: Stack Shuffler}

In praktisch allen höheren Programmiersprachen können Variablen in Form von Zuweisungen (bei imperativen Sprachen) oder Substitutionen (bei deklarativen\slash funktionalen Sprachen) verwendet werden. Variablen erfüllen dabei hauptsächlich zwei Aufgaben: sie helfen Werte zwischenzuspeichern und sie neu zu arrangieren für den Aufruf von Funktionen, Prozeduren oder Methoden. Darüber hinaus bieten Variablennamen semantische Brücken für den Programmierer bzw.\ die Programmiererin an, sich den Inhalt oder den Zweck eines Wertes zu merken.

Da es in Consize keine Variablen gibt, muss das Zwischenspeichern von Werten über den Datastack (beispielsweise per \verb|dup|) geschehen und das Rearrangieren von Werten über Stack-Shuffling gelöst werden. Es ist daher sehr hilfreich, weitere Wörter als Abstraktionen zum Stack-Shuffling zur Verfügung zu haben.

Da Variablennamen als semantische Brücken beim Programmieren fehlen, gibt es nur eine Möglichkeit, um Consize-Programme übersichtlich zu halten: Man muss die Definition von neuen Wörtern kurz halten und gegebenenfalls weitere Wörter einführen, um über geeignete Abstraktionen die Programme lesbar zu halten. Das ist auch der Grund, warum sich Wortdefinitionen oft nur über ein, zwei oder drei Zeilen erstrecken und praktisch nie über ein Dutzend Codezeilen hinausgehen. Und es unterstreicht auch die Bedeutung der Angabe von Stackeffekten. Stackeffekte beschreiben oft hinreichend genau, was ein Wort tut, so dass man sich das \emph{Wie} der Manipulation der Werte auf dem Datastack nicht merken muss. 

%>> % STACK SHUFFLING
%>> 
\begin{verbatim}
>> : 2drop ( x y -- ) drop drop ;
>> : 3drop ( x y z -- ) drop drop drop ;
>> : 2dup ( x y -- x y x y ) over over ;
>> : dupd ( x y -- x x y ) swap dup rot ;
>> : -rot ( x y z -- z x y ) rot rot ;
>> : rot4 ( x y z u -- y z u x ) [ rot ] dip swap ;
>> : -rot4 ( x y z u -- u x y z ) swap [ -rot ] dip ;
>> : 3dup ( x y z -- x y z x y z )
>>   rot dup -rot4 rot dup -rot4 rot dup -rot4 ;
>> : over ( x y -- x y x ) swap dup -rot ;
>> : 2over ( x y z -- x y z x y ) rot dup -rot4 rot dup -rot4 ;
>> : nip ( x y -- y ) swap drop ;
>> : 2nip ( x y z -- z ) nip nip ;
>> : pick ( x y z -- x y z x ) rot dup [ -rot ] dip ;
\end{verbatim}
%>> 

Es deutet sich bei den Definitionen einiger Stack-Shuffler wie z.B.\ \verb|rot| und \verb|-rot| an, dass es eine Alternative zum Stack-Shuffling gibt, die die Abwesenheit von Variablen elegant kompensiert: Kombinatoren, siehe Kap.~\ref{Sec:Kombinatoren}.

Zum Beispiel kann \verb|rot4| auch wie folgt definiert werden; das Stack-Shuffling ist im Kopf kaum mehr nachvollziehbar -- die Kommentare mögen bei den gedanklichen Schritten helfen.

\begin{verbatim}
: rot4 ( x y z u -- y z u x )
  [ ] swap push swap push % x y [ z u ]
  rot swap                % y x [ z u ]
  dup top swap pop top    % y x z u
  rot ;                   % y z u x
\end{verbatim}

Da die Stack-Shuffler der Consize-VM nicht über die ersten drei Elemente auf dem Datastack hinaus reichen, muss hier zu dem Trick gegriffen werden, Elemente vom Datstack in einen Stapel zu "`packen"', um auf das vierte Element von oben, hier \verb|x|, zugreifen zu können.

Mit Hilfe des \verb|dip|-Kombinators wird der Code radikal kürzer und gleichzeitig auch leicht nachvollziehbar. Es werden zunächst die unteren drei Werte, \verb|x| \verb|y| \verb|z|, auf dem Datastack per \verb|rot| rotiert, dann die obersten zwei Werte mit \verb|swap| getauscht.

Interessant ist auch, dass bei dem Einsatz von Kombinatoren die Reversibilität des Verhaltens von \verb|-rot4| zu \verb|rot4| klar zutage tritt: \verb|-rot4| tauscht erst die beiden obersten Elemente und rotiert dann die untersten drei. Die alternative Definition von \verb|-rot4| mittels

\begin{verbatim}
: -rot4 ( x y z u -- u x y z ) rot4 rot4 rot4 ;
\end{verbatim}

macht nicht nur deutlich schwerer nachvollziehbar, was die mehrfache Anwendung eines \verb|rot4| bewirkt, sondern sie hat auch die dreifachen Laufzeitkosten eines \verb|rot4|.

Mehr zu \verb|dip| und den anderen Kombinatoren steht in Kap.~\ref{Sec:Kombinatoren}.

\subsection{Freunde und Helferlein}

Bei der Arbeit mit Consize werden Sie feststellen, dass Sie einige Wortkombinationen sehr häufig benötigen. Es macht Sinn, eigene Wörter dafür einzuführen, um den Consize-Code lesbarer zu machen.

Die folgenden Wörter sind hilfreiche Begleiter bei der Arbeit mit Stapeln. 

%>> % FRIENDS & HELPERS
%>> 
\begin{verbatim}
>> : swapu ( itm stk -- stk' ) swap push ;
>> : unpush ( stk -- stk' itm ) dup pop swap top ;
>> : empty? ( stk -- t/f ) [ ] equal? ;
>> : size ( seq -- n ) dup empty? [ drop 0 ] [ pop size 1 + ] if ;
\end{verbatim}
%>> 

Die Anzahl der Elemente in einer Sequenz liefert \verb|size| zurück.

\begin{verbatim}
> clear [ ] size [ x y z ] size
0 3
\end{verbatim}

Der Datentyp "`nil"' ist in Consize nur indirekt über ein \verb|top| eines leeren Stapels definiert. Um \verb|nil| als Typ zugreifbar zu haben, gibt es das Wort \verb|nil|.

Das Wort \verb|delete| entfernt ein Wort mit seiner assoziierten Quotierung aus dem Wörterbuch der Consize-VM. Das Wort \verb|values| gibt -- im Gegensatz zu \verb|keys| -- alle mit den Schlüsseln assoziierten Zielwerte als Sequenz zurück.

\begin{verbatim}
>> : nil ( -- nil ) [ ] top ;
>> : delete ( itm -- ) get-dict dissoc set-dict ;
>> : values ( dict -- seq ) dup keys swap [ _|_ get ] swapu map ;
\end{verbatim}
%>> 

\section{Grundlegende Kombinatoren}

\subsection{Quotierungen aufrufen}

Wenn Consize ein Programm abarbeitet, ist es zu einem guten Teil mit der Auflösung benamter Abstraktionen beschäftigt: Das oberste Wort auf dem Callstack wird durch den Inhalt der mit ihm assoziierten Quotierung ersetzt. Genauer: Das Wort wird vom Callstack entfernt und die assoziierte Quotierung mit dem Callstack konkateniert.

Für den Aufruf anonymer Abstraktionen, d.h. Quotierungen, die nicht im Wörterbuch mit einem Wort verknüpft sind, gilt im Grunde derselbe Ablauf. Das Wort \verb|call| erwartet eine Quotierung auf dem Datastack, die es mit dem Callstack konkateniert. Die Notation des Stackeffekts soll genau das andeuten, was per \verb|call/cc| umgesetzt wird.

%>> % CALL A QUOTATION (ANONYMOUS ABSTRACTION)
%>> 
\begin{verbatim}
>> : call ( ... [ quot ] -- ... | quot )
>>   [ swap unpush rot concat continue ] call/cc ;
\end{verbatim}
%>>

Das per \verb|call/cc| initiierte Programm tauscht Data- und Callstack der aktuellen Continuation (\verb|swap|), holt das oberste Element (die Quotierung) vom Datastack (\verb|unpush|), bringt den Callstack wieder nach oben (\verb|rot|) und konkateniert Quotierung und Callstack miteinander (\verb|concat|). Anschließend übernimmt die so veränderte Continuation wieder die Aus\-füh\-rung (\verb|continue|).

Die Technik, mit \verb|call/cc| und \verb|continue| ein Programm zu unterbrechen, es zu modifizieren und dann fortzusetzen, nennt man "`\href{http://de.wikipedia.org/wiki/Metaprogrammierung}{Metaprogrammierung}"'. Das mit \verb|call/cc| mitgegebene Programm modifiziert das aktuell in der Ausführung begriffene Programm. Diese zur Laufzeit des Programm stattfindende Änderung nennt man deshalb bei Bedarf auch genauer "`Laufzeit-Metaprogrammierung"'.

Mit \verb|call| lässt sich die Ausführung eines Programms verzögern.

\begin{verbatim}
> clear [ 4 2 3 + ]
[ 4 2 3 + ]
> call
4 5
\end{verbatim}

Das Wort \verb|fcall| (für "`\emph{call via a function}") arbeitet ähnlich wie \verb|call|. Es erzeugt im Gegensatz zu \verb|call| über \verb|func| einen eigenen Ausführungs\-kon\-text, bekommt einen leeren Stapel als Datastack, wendet die Funktion darauf an (\verb|apply|) und liefert das Ausführungsergebnis als Stapel zurück und zwar mit dem "`umgekehrten"' Ergebnisstapel (\verb|reverse|).

\begin{verbatim}
>> : fcall ( quot -- seq ) get-dict func [ ] swap apply reverse ;  
\end{verbatim}
%>> 

\begin{verbatim}
> clear [ 4 2 3 + ] fcall
[ 4 5 ]
\end{verbatim}

\subsection{Boolesche Werte und die binäre Wahl}

Ein grundlegendes Feature einer turingvollständigen Programmiersprache ist es, binäre Entscheidungen treffen zu können: wähle -- abhängig von einem Entscheidungswert -- entweder dieses oder jenes. Im Idealfall ist der Entscheidungswert selber binär. Zu Ehren des Logikers \href{http://de.wikipedia.org/wiki/George\_Boole}{{\sc George Boole}} heißen diese beiden Werte "`boolesche Werte"' und werden mit "`wahr"' (\emph{true}) und "`falsch"' (\emph{false}) bezeichnet. In Consize repräsentieren die Wörter \verb|t| und \verb|f| auf dem Datastack diese beiden Optionen.

Die Consize-VM bietet von sich aus kein Wort an, das Entscheidungen realisiert; in vielen Programmiersprachen dient dazu das \emph{if}. Trotzdem -- und das ist das Spannende daran -- ist ein Wort für Entscheidungen nachrüstbar. Der \href{http://en.wikipedia.org/wiki/Lambda_calculus}{Lambda-Kalkül} macht es übrigens genauso.

Das Wort \verb|choose ( t/f this that -- this/that )| bilde die Grundlage für die binäre Auswahl. \verb|choose| erwartet auf dem Datastack einen booleschen Wert und zwei Wahlwerte, die wir im Stapeleffekt mit \verb|this| und \verb|that| bezeichnen. Abhängig vom booleschen Wert lässt \verb|choose| entweder \verb|this| oder \verb|that| auf dem Datastack zurück.

Die Bedeutung von \verb|t| und \verb|f| erschließt sich nur im Kontext des Wortes \verb|choose| -- und so bilden die mit den booleschen Werten assoziierten Programme exakt das beschriebene Verhalten nach: \verb|t| entfernt \verb|that| vom Datastack, um \verb|this| zu erhalten, \verb|f| macht es genau anders herum. Ohne den Kontext von \verb|choose| sind die booleschen Werte \verb|t| und \verb|f| bedeutungslos. 

%>> % BOOLEAN VALUES, BOOLEAN CHOICE
%>> 
\begin{verbatim}
>> : t ( this that -- this ) drop ;
>> : f ( this that -- that ) swap drop ;
>> : true  ( -- t ) \ t ;
>> : false ( -- f ) \ f ;
\end{verbatim}
%>> 

Die Wörter \verb|true| und \verb|false| dienen lediglich dem Lese- und Schreibkomfort; es ist rasch vergessen, das Escape-Wort einem \verb|t| bzw. \verb|f| voranzustellen.

Das Wort \verb|choose| muss per \verb|rot| den booleschen Wert lediglich oben auf den Datastack bringen, die Bedeutung (sprich: Semantik) von \verb|t| bzw. \verb|f| mit \verb|lookup| nachschlagen, und die ermittelte Quotierung mit \verb|call| aufrufen. Das Wort \verb|choose| macht nicht viel mehr als das mit \verb|t| bzw. \verb|f| assoziierte Verhalten zu aktivieren.

\begin{verbatim}
: choose ( t/f this that -- this/that ) rot lookup call ;
\end{verbatim}

Mit dieser Definition könnte man es bewenden lassen, doch es gibt einen guten Grund, die Auslegung boolescher Werte ein wenig zu erweitern.

Falls sich bei \verb|choose| weder ein \verb|t| noch ein \verb|f| an dritter Stelle, sondern ein beliebiger anderer Wert auf dem Datastack befindet, dann hat der Programmierer bzw.\ die Programmiererin den im Stapeleffekt dokumentierten "`Vertrag"' zum Gebrauch des Wortes \verb|choose| gebrochen. Die Folgen aus einem fälschlichen Gebrauch des Wortes hat der Programmierer bzw.\ die Programmiererin zu verantworten. Es spielt keine Rolle, ob der Fehlgebrauch unabsichtlich erfolgt oder nicht. Dieses Prinzip ist so wichtig, dass es nicht nur "`im richtigen Leben"' sondern auch in der Softwaretechnik zur Anwendung kommt: Wer einen Vertrag verletzt, darf die andere Partei (in dem Fall Consize) nicht für den entstehenden Schaden verantwortlich machen. Man muss beim Programmieren durchaus Vorsicht walten lassen.

Man könnte eine Vertragsverletzung durch eine Fehlermeldung abfangen, um auf das Problem aufmerksam zu machen und gegebenenfalls darauf zu reagieren. Allerdings verändert ein solches Vorgehen das Wort \verb|choose| von einer binären zu einer ternären Wahl: wähle \verb|this| im Fall von \verb|t|, \verb|that| im Fall von \verb|f| und mache etwas gänzlich anderes, wenn ein anderes Datum an dritter Position im Datastack steht. Das passt nicht zu unseren anfänglichen Intentionen, mit \verb|choose| lediglich eine binäre Auswahl treffen zu wollen.

Programmiersprachen mit \href{http://de.wikipedia.org/wiki/Dynamische\_Typisierung}{dynamischer Typisierung} -- Consize gehört dazu -- unterstützen zwar ein strikt binäres Verhalten, vermeiden aber Fehlermeldungen in der Regel durch eine simple Regelung: Jeder Wert, der sich von \verb|f| unterscheidet wird so interpretiert als sei er ein logisches \emph{true}. Wenn der dritte Wert auf dem Datastack nicht \verb|f| ist, dann wählt \verb|choose| \verb|this|, ansonsten \verb|that| aus. Die Definition von \verb|choose| verändert sich entsprechend geringfügig. Der Stern \verb|*| im Stapeleffekt steht für einen beliebigen Wert außer \verb|f|.

\begin{verbatim}
>> : choose ( f/* this that -- that/this )
>>   swap rot false equal? lookup call ;
\end{verbatim}
%>> 

Sprachen mit \href{http://de.wikipedia.org/wiki/Statische\_Typisierung}{statischer Typisierung} schließen den Fehlerfall durch eine Typüberprüfung vor Programmausführung aus. Wäre Consize eine statisch typisierte Sprache, könnte die Verwendung eines booleschen Wertes sicher gestellt werden, und es würde die eingangs angegebene Definition von \verb|choose| ausreichen.

Das Verhalten von \verb|choose| demonstriert folgende Beispieleingabe an der Konsole.

\begin{verbatim}
> clear false this that
f this that
> choose
that
> [ 1 2 3 ] this that choose
that this
\end{verbatim}

Die logischen Operationen der \href{http://de.wikipedia.org/wiki/Boolesche\_Algebra}{Booleschen Algebra} \verb|and| (Konjunktion), \verb|or| (Disjunktion) und \verb|not| (Negation) sind dieser erweiterten Interpretation logischer Werte ("`alles was nicht \verb|f| ist, ist logisch \verb|t|"') angepasst.

\begin{verbatim}
>> : and ( f/* f/* -- t/f ) over choose ; % Factor
>> : or  ( f/* f/* -- t/f ) dupd choose ; % Factor 
>> : not ( f/* -- t/f ) false true choose ;
\end{verbatim}
%>> 

Ein kurzes Beispiel zeigt den Gebrauch von \verb|and|.

\begin{verbatim}
> clear true true and
t
> false true and
t f
\end{verbatim}
  
\subsection{Entscheiden, wo's lang geht}

Das Wort \verb|choose| realisiert zwar eine binäre Wahl, doch werden damit noch keine unterschiedlichen Verhaltenskonsequenzen umgesetzt. Das ist erst dann der Fall, wenn \verb|this| und \verb|that| Quotierungen sind, die nach einem \verb|choose| per \verb|call| aufgerufen werden. Dafür gibt es das Wort \verb|if|; die Quotierungen werden im Stapeleffekt mit \verb|then| und \verb|else| bezeichnet. Dass die Auswirkungen auf den Datastack von den beiden Quotierungen abhängen und nicht vorhersehbar sind, deuten die Punkte auf der rechten Seite des Stapeleffekts an.

%>> % CONTROL
%>> 
\begin{verbatim}
>> : if ( f/* then else -- ... ) choose call ;
>> : if-not ( f/* then else -- ... ) swap if ;
>> : when ( f/* then -- ... ) [ ] if ;
>> : unless ( f/* else -- ... ) [ ] if-not ;
\end{verbatim}
%>> 

Die Wörter \verb|if-not|, \verb|when| und \verb|unless| sind hilfreiche Abstraktionen, die alle Variationen des \verb|if|-Themas abdecken: \verb|if-not| vertauscht die Rolle der beiden Quotierungen \verb|then| und \verb|else| (dem gedanklich eine Negation des booleschen Wertes entspricht), \verb|when| führt die Quotierung nur aus, wenn der vorangehende Wert als logisch \emph{true} gilt, \verb|unless|, wenn der vorangehende Wert \emph{false} ist.

\begin{verbatim}
> clear 5 dup 3 < [ 1 + ] [ 1 - ] if
4
> clear 5 dup 3 < [ 1 + ] [ 1 - ] if-not
6
> clear 5 true [ 1 + ] when
6
> clear 5 false [ 1 - ] unless
4
\end{verbatim}

Ein Bedingungswert außer \verb|f| gilt im Kontext eines \verb|if|, \verb|when| oder \verb|unless| als logisch \emph{true}, selbst wenn der Bedingungswert nicht gleich \verb|t| ist. Oft ist es so, dass man mit logisch wahren Bedingungswerten genau dann weiter arbeiten möchte, wenn sie nicht \verb|t| sind.

Die Wörter \verb|if*|, \verb|when*| und \verb|unless*| sind Varianten, die den Bedingungswert, so er denn logisch \emph{true} ist, vor der Ausführung eines gedachten \verb|if|, \verb|when| bzw. \verb|unless| auf dem Datastack duplizieren, so dass der Bedingungswert für die weitere Verarbeitung erhalten bleibt. Ist der Bedingungswert \verb|f|, so unterbleibt die Duplizierung und \verb|if*|, \verb|when*| bzw. \verb|unless*| arbeiten wie ihre "`sternlosen"' Vorbilder \verb|if|, \verb|when| und \verb|unless|.

\begin{verbatim}
>> : if*
>>   ( ..a ? true: '( ..a ? -- ..b ') false: '( ..a -- ..b ') -- ..b )
>>   pick [ drop call ] [ 2nip call ] if ; % Factor
>> : when* ( ? t -- ) over [ call ] [ 2drop ] if ; % Factor
>> : unless* ( ? f -- ) over [ drop ] [ nip call ] if ; % Factor
\end{verbatim}
%>> 

\begin{verbatim}
> clear 6 [ 1 + ] [ 0 ] if*
7
> clear false [ 1 + ] [ 0 ] if*
0
> 6 [ 1 + ] when*
7
> clear 5 6 [ 1 - ] unless*
5 6
> clear 5 false [ 1 - ] unless*
4
\end{verbatim}

Die mit dem Wort \verb|case| umgesetzte $n$-äre Entscheidung verallgemeinert das Konzept der binären \verb|if|-Entscheidung. Eine Handlungsalternative hängt bei \verb|case| nicht ab von zwei Alternativen (\verb|f| oder nicht \verb|f|), sondern von einem Wert aus einer Menge von Werten. Die Grundfunktionalität von \verb|case| ist bereits durch Mappings gegeben; nach einem \verb|get| muss im Grunde nur noch ein \verb|call| folgen. Mit dem Auswahlwert \verb|:else| besteht die Option, eine Reaktion zu initiieren, wenn kein sonstiger Auswahlwert in \verb|case| zutrifft.

Das Wort \verb|SYMBOL:| setzt mit dem nachfolgenden Wort, hier \verb|:else|, eine Definition auf, die das Wort mit sich selbst als Datenwert definiert (hier \verb|: :else \ :else ;|).

\begin{verbatim}
>> SYMBOL: :else 
>> : case ( val { val' quot ... } -- | quot )
>>   :else over [ _|_ ] get get call ;
\end{verbatim}
%>> 

Es ist zu beachten, dass die Zielwerte in einem "`\verb|case|-Mapping"' stets Quotierungen sind.

\begin{verbatim}
> clear 3 \ red
3 red
> { \ red [ 1 + ] \ blue [ 1 - ] :else [ ] } case
4
> blue { \ red [ 1 + ] \ blue [ 1 - ] :else [ ] } case
3
> black { \ red [ 1 + ] \ blue [ 1 - ] :else [ ] } case
3
\end{verbatim}

Die Verschachtlung von \verb|if|-Wörtern in den \verb|else|-Quotierungen eines \verb|if|-Worts erzeugt rasch unleserlichen Code. Als Alternative bietet sich das syntaktisch übersichtlichere \verb|cond| an, das die \verb|test|- und \verb|then|-Quo\-tie\-run\-gen verschachtlungsfrei zu notieren erlaubt. Einer \verb|test|-Quotierung folgt eine \verb|then|-Quotierung; im \verb|else|-Fall folgt die nächste \verb|test|-Quotierung usw.; die Terminologie orientiert sich an der Beschreibung des Stapeleffekts für \verb|if|. Eine optionale \verb|else|-Quotierung dient für den Fall, wenn alle \verb|test|-Quotierungen fehlschlagen.

\begin{verbatim}
>> : cond ( [ test1 then1 test2 then3 ... else ] -- | then/else )
>>   dup empty?                    % anything left to test?
>>     [ drop ]                    % no: quit
>>     [ unpush swap dup empty?    % only one quotation left?
>>       [ drop call ]             % yes: call 'else'
>>       [ unpush swap             % otherwise:
>>         [ ] \ cond push swapu   % prepare 'cond' recursion
>>         [ call ] 2dip if ]      % call 'testN' and apply 'if'
>>     if ]
>>   if ;
\end{verbatim}
%>> 

Per Konvention wird die Folge von Quotierungen vor einem \verb|cond| in runden Klammern notiert, nicht zuletzt, um eine visuell leichtere Abgrenzung zu haben. Beachten Sie, dass in den \verb|test|-Quotierungen in aller Regel ein \verb|dup| nötig ist, nicht zuletzt, um den Test-Wert für nachfolgende Bedingungen zu erhalten.

\begin{verbatim}
> clear

> 7 ( [ dup 0 > ] [ 1 + ] [ dup 0 < ] [ 1 - ] [ ] ) cond
8
> -7 ( [ dup 0 > ] [ 1 + ] [ dup 0 < ] [ 1 - ] [ ] ) cond
8 -8
> 0 ( [ dup 0 > ] [ 1 + ] [ dup 0 < ] [ 1 - ] [ ] ) cond
8 -8 0
\end{verbatim}

Ein \verb|case| lässt sich immer über ein \verb|cond| nachbilden, allerdings hat ein \verb|case| durch das Mapping eine konstante Laufzeit, während die Laufzeit von \verb|cond| mit jeder Verschachtlung linear anwächst. Umgekehrt kann nicht jedes \verb|cond| ohne weiteres in ein äquivalentes \verb|case| umgewandelt werden.

\section{Kombiniere: Kombinatoren}
\label{Sec:Kombinatoren}

Ein Wort heißt "`Kombinator"', wenn es eine oder mehr Quotierungen auf dem Datastack erwartet und die Quotierung(en) zur Abarbeitung bringt. So ist z.B.\ das Wort \verb|call| ein Kombinator, das Wort \verb|concat| hingegen nicht.

Die Kapitel~\ref{Sec:dip}-\ref{Sec:applyCombinators} behandeln verschiedene Klassen von Kombinatoren, die die Notwendigkeit des Stack-Shufflings minimieren und deshalb lesbarere Programme mit sich bringen. Die Definitionen der Kombinatoren orientieren sich in vielen Fällen an der konkatenativen Sprache Factor.
In Kap.~\ref{Sec:SequenceCombinators} geht es um Sequenzkombinatoren, die eine Anwendung eines Kombinators über eine Folge von Daten realisieren.

\subsection{"`Abtauch"'-Kombinatoren: \texttt{dip}}\label{Sec:dip}

Die \verb|dip|-Kombinatoren rufen wie ein \verb|call| eine Quotierung auf dem Datastack auf. Im Gegensatz zu einem reinen \verb|call| gehen die unmittelbar "`vor"' der Quotierung stehenden Daten für die Dauer des Aufrufs gleichermaßen auf Tauchstation; das englische Wort \emph{dip} ist hier im Sinne von "`abtauchen"' zu verstehen. Nach dem Aufruf erscheinen die "`abgetauchten"' Daten wieder auf dem Datastack. Das Wort \verb|dip| verbirgt ein Element vor der aufzurufenden Quotierung, das Wort \verb|2dip| verbirgt zwei Elemente, \verb|3dip| drei und \verb|4dip| vier.

%>> % CALL A QUOTATION AND HIDE ITEMS UNDERNEATH
%>> 
\begin{verbatim}
>> : dip ( x quot -- x ) [ ] rot push \ \ push concat call ;
>> : 2dip ( x y quot -- x y ) swap [ dip ] dip ;
>> : 3dip ( x y z quot -- x y z ) swap [ 2dip ] dip ;
>> : 4dip ( w x y z quot -- w x y z ) swap [ 3dip ] dip ;
\end{verbatim}
%>> 

\begin{verbatim}
> clear [ ] 4 5 [ push ] dip
[ 4 ] 5
> clear [ ] 4 5 [ drop ] 2dip
4 5
\end{verbatim}

Die Definition $n$-facher \verb|dip|-Kombinatoren folgt einem einfachen Schema: Das einleitende \verb|swap| und das beendende \verb|dip| bleiben immer gleich; lediglich die Quotierung greift auf die vorhergehende \verb|dip|-Definition zurück. In der Rückverfolgung des Bildungsgesetzes kann man auch fragen: Wie müsste demnach die Definition von \verb|dip| lauten? In der Quotierung wäre ein \verb|0dip| zu verwenden. Ein \verb|dip|, das \verb|0| Werte auf dem Datastack "`abtauchen"' lässt, ist identisch mit \verb|call|.

\begin{verbatim}
: dip ( x quot -- x ) swap [ call ] dip ;
\end{verbatim}

Diese Definition nimmt auf sich selbst Bezug und liefert auch in ihrer Auflösung keine weitere Erkenntnisse. Einen Hinweis, wie \verb|dip| implementiert werden kann, liefert sie dennoch: Es ist der Versuch, das im Stapeleffekt mit \verb|x| bezeichnete Element nicht mehr vor der Quotierung, sondern es per \verb|swap| hinter die Quotierung zu bekommen, so dass der \verb|call| der Quotierung \verb|quot| das Element \verb|x| nicht mehr erfasst.

Man kann dieses Verhalten zum Beispiel durch die Manipulation der aktuellen Continuation nach einem \verb|swap| erreichen; der Stapeleffekt deutet an, was hier gemacht wird.

\begin{verbatim}
: dip ( itm quot -- quot | call \ itm )
  swap [ swap unpush rot swap push \ \ push \ call push continue ]
  call/cc
\end{verbatim}

Grundsätzlich sollte man den Einsatz von Continuations vermeiden wann immer möglich; das hat formale Gründe, auf die in Kap.~\ref{Sec:DefSymbols} näher eingegangen wird.
Alternativ kann man den vor der Quotierung stehenden Wert ans Ende der Quotierung anhängen und mit einem Escape-Wort sicherstellen, dass der Wert nicht als zu interpretierendes Wort behandelt wird. Genau das tut die in der Prelude verwendete Definition, siehe oben. Alternative Definitionen sind:

\begin{verbatim}
: dip ( x quot -- x ) swap [ ] swap push \ \ push concat call ;
\end{verbatim}

\begin{verbatim}
: dip ( x quot -- x ) reverse \ \ push swap push reverse call ;
\end{verbatim}

Die alternativen Definitionen sind ebenso lesbar und einleuchtend wie die in der Prelude verwendete. Eine Messung der Laufzeiten könnte als Kriterium herangezogen werden, um die schnellste Lösung zu wählen. Da \verb|dip| durchaus laufzeitkritisch ist -- es spielt bei den nachfolgenden Kombinatoren eine entscheidende Rolle --, hat z.B.\ die konkatenative Sprache Factor \verb|dip| im Kern seiner VM aufgenommen. Angenommen, \verb|dip| sei als primitives Wort gegeben, dann sind \verb|call| und \verb|rot| definierbar als:

\begin{verbatim}
: call ( quot -- ... ) dup dip drop ;
: rot ( x y z -- y z x ) [ swap ] dip swap ;
\end{verbatim}

Es hängt sehr davon ab, welche Wörter als primitiv angesehen und in einer VM implementiert werden, und welche Wörter dann in Folge "`abgeleitete"' Wörter sind.

\subsection{Erhaltungskombinatoren: \texttt{keep}}

Die \verb|keep|-Kombinatoren rufen die Quotierung auf dem Datastack wie ein \verb|call| auf, sie bewahren (\emph{keep}) jedoch nach dem Aufruf eine Reihe von Daten, die sich "`vor"' der Quotierung und vor dem Aufruf auf dem Datastack befanden. Das Wort \verb|keep| erhält ein Datum, \verb|2keep| zwei Datenwerte und \verb|3keep| drei Datenwerte.

%>> % CALL A QUOTATION AND RESTORE ITEMS ON DATASTACK
%>> 
\begin{verbatim}
>> : keep  ( x quot -- x ) [ dup ] dip dip ;
>> : 2keep ( x y quot -- x y ) [ 2dup ] dip 2dip ;
>> : 3keep ( x y z quot -- x y z ) [ 3dup ] dip 3dip ;
\end{verbatim}
%>> 

Die Ausdrucksmittel für die Beschreibung der Stapeleffekte reichen nicht aus, um die Unterschiede zu den \verb|dip|-Kombinatoren hervorzuheben. Die tatsächlichen Auswirkungen auf den Datastack hängen von dem Aufruf der Quotierung ab.

\begin{verbatim}
> clear 2 3 [ + ] 2keep
5 2 3
\end{verbatim}

Beachten Sie, dass die \verb|keep|-Kombinatoren wie die \verb|dip|-Kombinatoren einem regulären Aufbau folgen -- diesmal ohne jegliche Brüche. Eine alternative Implementierung ist:

\begin{verbatim}
: keep  ( x quot -- x ) over [ call ] dip ; % see Factor
: 2keep ( x y quot -- x y ) 2over [ call ] 2dip ;
: 3keep ( x y z quot -- x y z ) 3over [ call ] 3dip ;
\end{verbatim}

Beachten Sie, dass \verb|3over| in der Prelude nicht definiert ist.

\subsection{Cleave-Kombinatoren: \texttt{bi}, \texttt{tri} und \texttt{cleave}}

Das Wort \emph{cleave} heißt hier soviel wie "`bewahren"', "`festhalten"', "`teilen"'.

Die \verb|bi|- und \verb|tri|-Kombinatoren wenden zwei bzw.\ drei Quotierungen nacheinander auf den Datastack an und restaurieren ein, zwei oder drei Werte auf dem Datastack vor dem Aufruf der nächsten Quotierung. Im Stapeleffekt sind die Quotierungen mit \verb|p|, \verb|q| und \verb|r| bezeichnet, die restaurierten Werte mit \verb|x|, \verb|y| und \verb|z|.

%>> % CALL 2, 3 QUOTATIONS IN SEQUENCE, RESTORE ITEM(S) FOR NEXT CALL
%>> % "The cleave combinators apply multiple quotations to a single
%>> % value or set of values." [Factor]
%>> 
\begin{verbatim}
>> : bi ( x p q -- ) [ keep ] dip call ;
>> : 2bi ( x y p q -- ) [ 2keep ] dip call ;
>> : 3bi ( x y z p q -- ) [ 3keep ] dip call ;
\end{verbatim}
%>> 

\begin{verbatim}
>> : tri ( x p q r -- ) [ [ keep ] dip keep ] dip call ;
>> : 2tri ( x y p q r -- ) [ [ 2keep ] dip 2keep ] dip call ;
>> : 3tri ( x y z p q r -- ) [ [ 3keep ] dip 3keep ] dip call ;
\end{verbatim}
%>> 

Ein paar wenige Beispiele mögen die Arbeitsweise von \verb|bi|- bzw. \verb|tri|-Kombinatoren veranschaulichen.

\begin{verbatim}
> clear 2 [ 1 + ] [ dup * ] bi
3 4
> [ + ] [ * ] 2bi
7 12
> clear 2 [ 1 + ] [ dup * ] [ 1 - ] tri
3 4 1
\end{verbatim}

Der \verb|cleave|-Kombinator verallgemeinert die \verb|bi|- bzw. \verb|tri|-Kombinatoren. Der \verb|cleave|-Kombinator nimmt beliebige viele Quotierungen als Sequenz entgegen und wendet die Quotierungen nacheinander auf einen (\verb|cleave|), auf zwei (\verb|2cleave|) bzw.\ drei (\verb|3cleave|) Werte auf dem Datastack an; vor jedem Aufruf werden die Werte restauriert. Das Wort \verb|each| ist in Kap.~\ref{Sec:SequenceCombinators} definiert.

\begin{verbatim}
>> : cleave ( x [ p q ... ] -- ) [ keep ] each drop ;
>> : 2cleave ( x y [ p q ... ] -- ) [ 2keep ] each 2drop ;
>> : 3cleave ( x y z [ p q ... ] -- ) [ 3keep ] each 3drop ;
\end{verbatim}
%>> 

Das folgende Beispiel ist identisch mit dem vorstehenden \verb|tri|-Beispiel.

\begin{verbatim}
> clear 2 ( [ 1 + ] [ dup * ] [ 1 - ] ) cleave
3 4 1
\end{verbatim}

\subsection{Spread-Kombinatoren: \texttt{bi*} und \texttt{tri*}}

Der \verb|bi*|-Kombinator erwartet zwei Quotierungen (\verb|p| und \verb|q|), der \verb|tri*|-Kombinator drei Quotierungen (\verb|p|, \verb|q| und \verb|r|). Die Quotierungen verarbeiten im Fall von \verb|bi*| und \verb|tri*| jeweils nur einen Wert, bei \verb|2bi*| und \verb|2tri*| jeweils zwei Werte. Die Quotierungen werden auf die Verarbeitung der Stapelwerte verteilt -- \emph{spread} bedeutet soviel wie "`verteilen"', "`spreizen"'.

Im Fall von \verb|bi*| arbeitet \verb|p| auf \verb|x| und \verb|q| auf \verb|y|. Und im Fall von \verb|2bi*| verarbeitet \verb|p| die Werte \verb|w| und \verb|x| und \verb|q| die Werte \verb|y| und \verb|z|.

%>> % CALL 1ST QUOTATION ON 1ST ITEM, 2ND QUOTATION ON 2ND ITEM
%>> % "The spread combinators apply multiple quotations to multiple
%>> % values. The asterisk (*) suffixed to these words' names
%>> % signifies that they are spread combinators." [Factor]
%>> 
%>> % : bi* ( #X #Y [ @P ] [ @Q ] ==> #X [ @P ] | call \ #Y [ @Q ] call )
%>> % : bi* ( #X #Y [ @P ] [ @Q ] ==> #X | @P \ #Y @Q )
\begin{verbatim}
>> : bi* ( x y p q -- ) [ dip ] dip call ;
>> : 2bi* ( w x y z p q -- ) [ 2dip ] dip call ;
\end{verbatim}
%>> 

\begin{verbatim}
> clear 2 3 [ 1 + ] [ dup * ] bi*
3 9
> clear 1 2 3 4 [ + ] [ * ] 2bi*
3 12
\end{verbatim}

Die Kombinatoren \verb|tri*| und \verb|2tri*| arbeiten entsprechend.

%>> % : tri* ( x y z p q r -- ) [ [ 2dip ] dip dip ] dip call ; % Factor
\begin{verbatim}
>> : tri* ( x y z p q r -- ) [ 2dip ] 2dip bi* ;
>> : 2tri* ( u v w x y z p q r -- ) [ 4dip ] 2dip 2bi* ;
\end{verbatim}
%>> 

\begin{verbatim}
> clear 4 3 2 [ 1 + ] [ dup * ] [ 1 - ] tri*
5 9 1
> clear 6 5 4 3 2 1 [ + ] [ * ] [ - ] 2tri*
11 12 1
\end{verbatim}

Die Verallgemeinerung der \verb|bi*|- und \verb|tri*|-Kombinatoren in Form eines \verb|spread|- bzw. \verb|2spread|-Wortes (analog zu \verb|cleave| bzw. \verb|2cleave|) wird derzeit nicht unterstützt.

%>> % The word 'spread' is currently not supported
%>> 

\subsection{Apply-Kombinatoren: \texttt{bi@} und \texttt{tri@}}
\label{Sec:applyCombinators}

Die Apply-Kombinatoren sind "`Anwendungskombinatoren"' (\emph{apply} heißt "`anwenden"'), die wie Spread-Kombinatoren arbeiten, im Gegensatz dazu jedoch nur eine Quotierung erwarten, die entsprechend \verb|dup|liziert wird. Die Definitionen sind selbsterklärend. 

%>> % CALL ONE QUOTATION ON MULTIPLE ITEMS
%>> % "The apply combinators apply a single quotation to multiple values.
%>> %  The at sign (@) suffixed to these words' names signifies that they
%>> %  are apply combinators." [Factor]
%>> 
\begin{verbatim}
>> : bi@ ( x y quot -- ) dup bi* ;
>> : 2bi@ ( w x y z quot -- ) dup 2bi* ;
>> : tri@ ( x y z quot -- ) dup dup tri* ;
>> : 2tri@ ( u v w x y z quot -- ) dup dup 2tri* ;
\end{verbatim}
%>> 

\begin{verbatim}
> clear 3 4 [ dup * ] bi@
9 16
> clear 6 5 4 3 2 1 [ * ] 2tri@
30 12 2
\end{verbatim}

\subsection{Sequenzkombinatoren: \texttt{each} und Co.}
\label{Sec:SequenceCombinators}

Sequenzkombinatoren wenden eine Quotierung \verb|quot| auf jedes Element einer Sequenz \verb|seq| an. Damit stehen Abstraktionen zur Verfügung, die dasselbe erreichen, wofür in anderen Programmiersprachen Schleifenkonstrukte wie "`\verb|for|"' und sogenannte Iteratoren zur Verfügung stehen. In einer funktionalen Sprache wie Consize geht man die Elemente einer Sequenz nicht per Index, sondern einfach der Reihe nach durch.

Der \verb|each|-Kombinator ist der elementarste der Sequenzkombinatoren, er legt die Ergebnisse der Anwendung der Quotierung auf die einzelnen Elemente schlicht auf dem Datastack ab.

%>> % SEQUENCE COMBINATORS
%>> 
\begin{verbatim}
>> : each ( seq quot -- ... )
>>   swap dup empty?
>>     [ 2drop ]
>>     [ unpush -rot over [ call ] 2dip each ]
>>   if ;
\end{verbatim}
%>> 

\begin{verbatim}
> clear ( 1 2 3 4 ) [ dup * ] each
1 4 9 16
\end{verbatim}

Das Wort \verb|map| fasst die Ergebnisse wiederum in einer Sequenz zusammen.

\begin{verbatim}
>> : map ( seq quot -- seq' )
>>   [ push ] concat [ ] -rot each reverse ;
\end{verbatim}

Die Definition von \verb|map| erweitert das durch die Quotierung dargestellte Programm um ein \verb|push|, das die einzelnen Ergebnis auf einen per \verb|[ ]| und \verb|-rot| bereit gestellten Stapel ablegt. Am Schluss stellt \verb|reverse| die korrekte Reihenfolge her.

\begin{verbatim}
> clear ( 1 2 3 4 ) [ dup * ] map
[ 1 4 9 16 ]
\end{verbatim}

Das Wort \verb|reduce| aggregiert die Werte einer Sequenz zu einem Einzelwert bezüglicher einer Operation, die durch eine Quotierung repräsentiert wird. Die Annahme ist zum einen, dass die Quotierung eine zweiwertige Operation ist, d.h. dass sie zwei Werte auf dem Datastack erwartet. Zum anderen ist \verb|identity| das neutrale Element dieser Operation.

\begin{verbatim}
>> : reduce ( seq identity quot -- res ) [ swap ] dip each ;
\end{verbatim}
%>> 

Ein paar Beispiele: Das neutrale Element der Addition ist \verb|0|, das der Multiplikation \verb|1| und das der Konkatenation \verb|[ ]|.

\begin{verbatim}
> clear ( 1 4 9 16 ) 0 [ + ] reduce
30
> clear ( ) 0 [ + ] reduce
0
> clear ( 2 3 4 ) 1 [ * ] reduce
24
> clear ( [ 1 ] [ 2 ] [ 3 4 ] ) [ ] [ concat ] reduce
[ 1 2 3 4 ]
\end{verbatim}

Die Wörter \verb|map| und \verb|reduce| sind ein besonderes Paar, da sie ein gewichtiges Prinzip verkörpern, das als Idee z.B.\ die Konzeption der Sprache \href{http://de.wikipedia.org/wiki/MapReduce}{MapReduce} geprägt hat: Mit \verb|map| kann eine Operation in Form einer Quotierung im Grunde parallel auf den einzelnen Daten einer Sequenz arbeiten, mit \verb|reduce| werden die Einzelergebnisse zusammengetragen und ausgewertet. Nach diesem Prinzip verarbeitet Google mit MapReduce die riesigen Datenmengen, die bei der Erfassung von Webseiten und anderen Datenquellen anfallen. Die Berechnung verteilt Google auf Rechencluster von mehreren tausend Rechnern.

Das Wort \verb|filter| nutzt die Quotierung als Prädikat, um nur die Elemente aus der Sequenz herauszufiltern, die den Prädikatstest bestehen. Eine Quotierung heißt Prädikat, wenn sie als Ergebnis ihrer Ausführung entweder ein \emph{true} oder \emph{false} in Form von \verb|t| bzw.\ \verb|f| auf dem Datastack ablegt.

\begin{verbatim}
>> : filter ( seq quot -- seq' ) % quot is a predicate
>>   [ dup ] swap concat
>>   [ [ push ] [ drop ] if ] concat
>>   [ ] -rot each reverse ;
\end{verbatim}
%>> 

Auch das Wort \verb|filter| erweitert ähnlich wie \verb|map| das Programm der Quotierung: ein vorangestelltes \verb|dup| dupliziert die Werte zur Prüfung durch das Prädikat. Abhängig von dem Ergebnis der Prüfung wird der untersuchte Werte entweder auf dem Stapel abgelegt oder verworfen. Auch hier ist ein abschließendes \verb|reverse| notwendig.

\begin{verbatim}
> clear ( 1 3 -4 5 0 7 2 ) [ 0 > ] filter
[ 1 3 5 7 2 ]
\end{verbatim}

Das Wort \verb|remove| macht das Gegenteil von \verb|filter|: Es fasst die von \verb|filter| verworfenen Elemente zusammen. Die Definition macht genau das, indem es das Prädikatsergebnis mit \verb|not| negiert.

\begin{verbatim}
>> : remove ( seq quot -- seq' ) [ not ] concat filter ;
\end{verbatim}
%>> 

\begin{verbatim}
> clear ( 1 3 -4 5 0 7 2 ) [ 0 > ] remove
[ -4 0 ]
\end{verbatim}

\section{Erweiterung der Consize-Grammatik}
\label{Sec:Grammatik+}

Consize hat eine derart einfache Grammatik, die jeden Programmtext erfolgreich in eine Folge von Wörtern zerlegen lässt. Leerräume im Programmtext grenzen die Wörter voneinander ab, siehe auch Kap.~\ref{Sec:Parsing}.

Die Großzügigkeit der Grammatik hat eine Schattenseite: Es fehlt die Möglichkeit, den Code syntaktisch zu strukturieren und Literale für Stapel und Mappings zu verwenden.

Als Literale bezeichnet man syntaktische Vereinbarungen, die eine Notation zur direkten Angabe eines Datentypen vorsehen. Zum Beispiel kodiert die Schreibweise \verb|[ x y ]| einen Stapel, was einem die wenig leserliche Form der Stapelkonstruktion erspart:

\begin{verbatim}
emptystack \ y push \ x push
\end{verbatim}

Kap.~\ref{Sec:Literale} führt Literale für zusammengesetzte Datentypen, sprich Stapel und Mappings ein.

Eine syntaktische Struktur bietet Ihnen etwa die aus diesem Kapitel bekannte Form, neue Wörter zu definieren. Nach dem einleitenden Doppelpunkt folgt das Wort, der optionale Stapeleffekt und die definierenden Wörter bis zum Semikolon. Damit befasst sich Kap.~\ref{Sec:DefWords}. In Kap.~\ref{Sec:DefSymbols} wird eine weitere, kleine syntatische Struktur zur Definition von Wörtern eingeführt, die als Symbole fungieren.

\subsection{Literale für zusammengesetzte Datentypen}
\label{Sec:Literale}

Eine Literal-Notation für zusammengesetzte Datentypen ist leicht in Consize integriert, wenn die Klammern eigenständige Wörter sind und nicht mit dem Wort verschmelzen. Die verschmelzende Schreibweise \verb|[x y]| hat das Problem, die zwei Wörter \verb|[x| und \verb|y]| jeweils darauf hin untersuchen zu müssen, ob sie mit einem öffnenden Klammerzeichen beginnen oder einem schließenden Klammerzeichen enden. Dieser Analyse muss prinzipiell jedes Wort unterzogen werden. Ein unnötiger Aufwand, da es auch einfacher geht.

Die nicht-verschmelzende Notation \verb|[ x y ]| lässt die Klammern eigen\-stän\-di\-ge Wörter sein. Jetzt dient das Wort \verb|[| als Auslöser, um die Suche nach dem schließenden Klammerwort zu starten und aus den Elementen zwischen den Klammer-Wörtern den Stapel zu konstruieren. Sobald eine öffnende Klammern die Suche triggert, wird das Klammer-Wort auf dem Datastack abgelegt und die schließende Klammer in der Continuation gesucht. 

%>> % ENHANCE "GRAMMAR" (BRACKET PARSER)
%>> 
\begin{verbatim}
>> : [ ( -- quot ) \ [ [ scan4] continue ] call/cc ;
>> : ( ( -- seq  ) \ ( [ scan4] continue ] call/cc ;
>> : { ( -- map  ) \ { [ scan4] continue ] call/cc ;
\end{verbatim}
%>> 

Das Wort \verb|scan4]| sucht nach \verb|]|, \verb|}| bzw.\ \verb|)| in der aktuellen Continuation und liefert im Fall von eckigen und runden Klammern einen Stapel und bei geschweiften Klammern ein Mapping zurück. Worin unterscheiden sich die Notationen im Detail?

Die eckigen Klammern repräsentieren eine Quotierung und übernehmen alle Wörter zwischen den Klammern so wie sie sind. Runde Klammern erlauben die Ausführung von Wörtern zwischen der öffnenden und der schließenden runden Klammer.

\begin{verbatim}
> clear [ 1 dup 1 + dup 1 + ]
[ 1 dup 1 + dup 1 + ]
> clear ( 1 dup 1 + dup 1 + )
[ 1 2 3 ]
\end{verbatim}

Die geschweiften Klammern erzeugen ein Mapping, die -- wie runde Klammern -- die Wörter zwischen den Klammern ausführen und dann erst das Mapping bilden.

\begin{verbatim}
> clear { 1 dup 1 + 3 4 }
{ 1 2 3 4 }
\end{verbatim}

Natürlich werden Verschachtlungen von Klammern vom Wort \verb|scan4]| berücksichtigt. Ebenso beachtet \verb|scan4]| die Wirkung des Wortes \verb|\| als Escape-Wort. Erreicht \verb|scan4]| das Ende des Callstacks, ohne dass die Klammern aufgelöst werden konnten, fehlt irgendwo zu einer öffnenden Klammer ihr schließendes Pendant, was eine Fehlermeldung nach sich zieht.

\begin{verbatim}
>> : scan4] ( ds cs -- ds' cs' )
>>   unpush dup
>>   { \ ]   [ drop [ ] rot scan4[ ]
>>     \ }   over
>>     \ )   over
>>     \ [   [ rot swapu swap scan4] scan4] ] 
>>     \ {   over
>>     \ (   over
>>     \ \   [ drop unpush rot swapu \ \ push swap scan4] ]
>>     :else [ rot swapu swap scan4] ]
>>     nil   [ \ syntax-error [ unbalanced brackets ] _|_ ]
>>   } case ;
\end{verbatim}
%>> 

Das Wort \verb|over| realisiert innerhalb der geschweiften Klammern zum \verb|case|-Wort einen kleinen \href{http://de.wikipedia.org/wiki/Hack}{Hack}. Code-Dopplungen werden per \verb|over| einfach in die nächste Zeile übertragen.

Ist eine schließende Klammer gefunden, wird von hinten her das Feld "`aufgeräumt"': Die Elemente werden durch \verb|scan4[| vom Ende her per \verb|push| solange in einen Stapel befördert, bis die öffnende Klammer gefunden ist. Die öffnende Klammer bestimmt, was mit den aufgesammelten Elementen passiert: Werden die Elemente unverändert gelassen (Quotierung mit \verb|[|), werden sie innerhalb der Klammern in einem eigenen Kontext mit \verb|fcall| aufgerufen (so der Fall bei \verb|(| und \verb|{|), wird aus dem Ergebnis ein Mapping gemacht (was bei \verb|{| der Fall ist)?

\begin{verbatim}    
>> : scan4[ ( cs' stk ds' -- ds'' cs'' )
>>   unpush dup
>>   { \ [   [ drop swap               push swap ]
>>     \ {   [ drop swap fcall mapping push swap ]
>>     \ (   [ drop swap fcall         push swap ]
>>     \ \   [ drop unpush rot swapu \ \ push swap scan4[ ] 
>>     :else [ rot swapu swap scan4[ ]
>>     nil   [ \ syntax-error [ unbalanced brackets ] _|_ ]
>>   } case ;
\end{verbatim}
%>> 

Consize verlangt immer eine ausgewogene Anzahl an öffnenden und schließenden Klammern, nicht jedoch, dass die schließende Klammer zur öff\-nen\-den passt. Auch wenn das höchst verwirrend zu lesen ist (und daher niemals so geschrieben werden sollte), das folgende Beispiel liefert ein Mapping, obwohl die schließende Klammer nicht passt.

\begin{verbatim}
> clear { 1 dup 2 3 )
{ 1 1 2 3 }
\end{verbatim}

Sollen die Elemente für ein Mapping nicht ausgeführt werden, so ist mit einer Quotierung und \verb|mapping| zu arbeiten:

\begin{verbatim}
> clear { 1 dup 2 3 }
{ 1 1 2 3 }
> clear [ 1 dup 2 3 ] mapping
{ 1 dup 2 3 }
\end{verbatim}

Mit \verb|parse-quot| werden die innerhalb einer Quotierung verwendeten Li\-te\-ral-Notationen in die entsprechenden Datentypen umgewandelt. 

\begin{verbatim}  
>> : parse-quot ( quot -- quot' )
>>   \ [ push reverse \ ] push reverse call ;
\end{verbatim}
%>> 

Die Folge der Wörter \verb|[|, \verb|1|, \verb|2|, \verb|3| und \verb|]| sieht zwar aus wie die Notation eines Stapels, es sind aber tatsächlich nur fünf Wörter, wie sich durch \verb|top| im Beispiel zeigt.

\begin{verbatim}
> clear ( \ [ 1 2 3 \ ] )
[ [ 1 2 3 ] ]
> top
[
\end{verbatim}

Nach der Anwendung von \verb|parse-quot| ist die Wortfolge in einen Stapel verwandelt worden. Die Intention der Notation als Literal muss per \verb|parse-quot| ausdrücklich eingefordert werden.

\begin{verbatim}
> clear ( \ [ 1 2 3 \ ] )
[ [ 1 2 3 ] ]
> parse-quot
[ [ 1 2 3 ] ]
> top
[ 1 2 3 ]
\end{verbatim}

\subsection{Neue Wörter mit \texttt{:} bis \texttt{;} definieren}
\label{Sec:DefWords}

Ohne eine spezielle Syntax zur Definition neuer Wörter bedarf es mindestens des Wortes \verb|def|, um ein neues Wort mit einem beliebigen Datum im Wörterbuch eintragen zu können.

%>> % WRITE PROGRAMS, DEFINE WORDS
%>> 
\begin{verbatim}
>> : def ( wrd itm -- ) swap get-dict assoc set-dict ;
\end{verbatim}
%>> 

Für die Ablage aller Stapeleffekte gibt es das Wort \verb|*effect*|. Das zu \verb|*effect*| abgelegte Mapping speichert Wörter und die mit ihnen verbundenen Stapeleffekte.

\begin{verbatim}
>> : *effect* ( -- ) { } ; 
\end{verbatim}
%>> 

Das Wort \verb|def+| ist ein um die Speicherung des Stapeleffekts erweitertes \verb|def|.

\begin{verbatim}      
>> : def+ ( wrd [ effect ] [ body ] -- )
>>   rot dup rot def *effect* assoc [ ] swapu \ *effect* swap def ;
\end{verbatim}

Das Wort \verb|:| leitet die Definition eines neues Wortes unter einer über\-sicht\-lich\-er\-en Syntax ein. In der aktuellen Continuation wird mit \verb|scan4;| nach dem Wort \verb|;| gesucht, das das Ende der Definition markiert. Die Definition wird in ihre Anteile zerlegt und zur Verarbeitung durch \verb|def+| aufbereitet.

\begin{verbatim}
>> : : ( | ... '; -- quot ) 
>>   [ [ ] swap scan4; destruct-definition def+ continue ] call/cc ;
\end{verbatim}
%>> 

Das Wort \verb|scan4;| arbeitet wie ein \verb|scan4]| oder \verb|scan4[|. Kleine Unterschiede im Stapeleffekt erzeugen leichte Variationen im Aufbau des Programmtextes.

\begin{verbatim}
>> : scan4; ( ds [ ] cs -- ds cs' quot )
>>   unpush dup
>>   { \ ;   [ drop swap reverse ]
>>     \ \   [ drop unpush rot \ \ push swapu swap scan4; ]
>>     :else [ rot swapu swap scan4; ]
>>     nil   [ \ syntax-error [ incomplete definition ] _|_ ]
>>   } case ;
\end{verbatim}
%>> 

Das Wort \verb|destruct-definition| zerlegt die zwischen \verb|:| und \verb|;| aufgesammelten Wörter in das zu definierende Wort, den Stapeleffekt und den "`Rest"', den eigentlichen Rumpf der Wortdefinition. Per \verb|parse-quot| werden Literal-Notationen in die entsprechenden Datentypen umgewandelt. Die Umwandlung erfolgt damit zur Definitionszeit eines Worts und nicht zur Laufzeit -- was in einer frühen Version von Consize der Fall war und beträchtliche Laufzeiteinbußen mit sich brachte.

\begin{verbatim}  
>> : destruct-definition ( quot -- wrd stackeffect body ) 
>>   dup top swap pop      % extract word
>>   [ ] swap              % prepare extraction of stack effect
>>   dup top \ ( equal?    % extract stack effect
>>     [ pop look4) ] when % if given
>>   parse-quot ;          % and parse quotation
\end{verbatim}
%>> 

Auch das Wort \verb|look4)| unterscheidet sich in seiner Arbeitsweise im Grunde nicht von \verb|scan4]|, \verb|scan4[| und \verb|scan4;|.

\begin{verbatim} 
>> : look4) ( [ ... ] quot -- [ ... ]' quot' )
>>   unpush dup
>>   { \ )   [ drop swap reverse swap ]
>>     \ \   [ drop unpush rot swapu swap look4) ]
>>     :else [ rot swapu swap look4) ]
>>     nil   [ \ syntax-error [ incomplete stack effect ] _|_ ]
>>   } case ;
\end{verbatim}
%>> 
  
\subsection{Symbole}
\label{Sec:DefSymbols}

In Consize erwartet jedes Wort, die zu verarbeitenden Daten auf dem Datastack vorzufinden. Bis auf die Wörter \verb|call/cc| und \verb|get-dict| gilt das ausnahmslos für alle Wörter der Consize-VM und für die Wörter der Prelude. Das drückt sich auch in der Postfix-Notation aus; die auf den Daten operierenden Wörter kommen immer \emph{nach} den Daten.

In der Prelude gibt es wenige Ausnahmen von dieser Regel -- und dazu gehören all die Wörter dieses Kapitels, die die Grammatik von Consize erweitern: \verb|[|, \verb|(|, \verb|{|, \verb|:| und das noch zu besprechende \verb|SYMBOL:|. Wir klassifizieren diese Wörter als "`syntaktische Wörter"'. Syntaktische Wörter benötigen Daten, die nicht auf dem Datastack, sondern auf dem Callstack zu finden sind. Das ist auf den ersten Blick nicht verträglich mit dem konkatenativen Paradigma.

Die Ordnung wird dadurch wiederhergestellt, weil diese Wörter mit Hilfe von \verb|call/cc| nur einen definierten Teil der Daten vom Callstack abgreifen, die prinzipiell hätten auch auf dem Datastack stehen können, wozu es dann eines entsprechenden "`normalen"' Wortes bedürfte. Ganz deutlich wird das am Beispiel des Wortes \verb|:|, das eine Wortdefinition einleitet. Die Daten vom Callstack werden aufbereitet zur Verarbeitung durch \verb|def+|. Das syntaktische Wort \verb|:| hat in \verb|def+| seinen "`normalen"', den Datastack verarbeitenden Gegenpart. Bei \verb|[|, \verb|(| und \verb|{| ist es sogar noch einfacher. Diese Wörter repräsentieren zusammen mit ihren schließenden Gegenstücken ein einziges Datum auf dem Datastack.

Syntaktische Wörter haben also einzig die Funktion, aus der "`normalen"' Postfix-Notation auszubrechen, um eine syntaktische Struktur anzubieten, von der man sich Vorteile in der Wahrnehmung durch den Programmierer bzw. die Programmiererin verspricht. Auf gut deutsch: Der Programmtext soll lesbarer werden. Lesbarkeit und syntaktische Spielereien stehen nicht im Widerspruch zum konkatenativen Paradigma, sie erfordern nur die Auflösung der syntaktischen Form in "`normale"' konkaktenative Strukturen.

Ganz in diesem Sinne arbeitet das syntaktische Wort \verb|SYMBOL:|. Es erwartet genau ein Wort oben auf dem Callstack und baut den Code für die folgende Definitionsstruktur auf. Aus

\begin{verbatim}
SYMBOL: <word>
\end{verbatim}

wird

\begin{verbatim}
: <word> \ <word> ;
\end{verbatim}

Die Definition (ohne Stapeleffekt) sorgt dafür, dass das Wort sich selbst als Datum auf dem Datastack ablegt. Und genau das versteht Consize unter einem Symbol. Symbole sind Wörter, die sich selbst als Datum repräsentieren.

\begin{verbatim}
>> : SYMBOL: ( | itm -- )
>>   [ unpush dup ( \ ; ) swapu \ \ push swapu \ : push
>>     swap concat continue ] call/cc ;
\end{verbatim}
%>>   

Jeder Gebrauch von \verb|call/cc|, der nicht zur Umsetzung eines syntaktischen Wortes dient, muss ernsthaft die Verträglichkeit mit dem konkatenativen Paradigma hinterfragen. Das Wort \verb|call/cc| macht die Tür zur Manipulation der aktuellen Continuation weiter auf als es für das konkatenative Paradigma notwendig ist. Tatsächlich stehen Continuations in jüngerer Zeit in der Kritik, bei "`unsachgemäßem"' Gebrauch unverträglich mit funktionalen Sprachen zu sein (Consize ist eine funktionale Sprache), was weitreichende und ungewollte Konsequenzen haben kann.\footnote{\url{http://lambda-the-ultimate.org/node/4586} bietet einen guten Einstieg in die Diskussion.} Als Lösung gelten begrenzte Continuations (\emph{delimited continuations}, die auch unter dem Namen \emph{partial continuations} firmieren), die einen unsachgemäßen Gebrauch erst gar nicht ermöglichen.

% TODO: Delimited Continuations für Consize definieren

\section{Die Interaktion mit Consize}

\subsection{Repräsentation von Daten und ihre Ausgabe}

Die Wörter \verb|<space>| und \verb|<newline>| sind nützliche Helferlein. Beide Wörter erleichtern ein wenig die Konstruktion von Ausgaben über die Konsole. 

%>> % PRINTING
%>> 
\begin{verbatim}
>> : <space> ( -- space ) \space char ;
>> : <newline> ( -- newline ) \newline char ;
\end{verbatim}
%>> 

Das Wort \verb|println| steht für \emph{print line}; eine Abstraktion, die die Ausgabe auf der Konsole mit einem Zeilenumbruch enden lässt.

\begin{verbatim}
>> : println ( -- ) print <newline> print flush ;
\end{verbatim}
%>> 

Die Consize-VM hat keinen Zugriff darauf, wie Daten innerhalb der VM gespeichert und kodiert sind. Es ist nicht einmal festgelegt, wie Stapel, Mappings, Funktionen und "`Nichts"' ausgegeben werden sollen. Nur für Wörter ist durch \verb|print| in der Consize-VM eine Repräsentation gegeben, die dem Wortnamen entspricht.

Für die Repräsentation der verschiedensten Datentypen zeichnet sich das Wort \verb|repr| verantwortlich. Hier wird festgelegt, wie die Werte der Datentypen dargestellt (repräsentiert) werden sollen. Aus naheliegenden Gründen werden die Literal-Notationen für Stapel und Mappings verwendet wie Sie sie bereits aus Kap.~\ref{Sec:Basics} kennen. Nicht zuletzt erlaubt die Symmetrie von Repräsentation und Literal-Notation, dass eine Repräsentation eines Wertes grundsätzlich auch wieder von Consize eingelesen werden kann. Nur für Funktionen gibt es keine sinnvolle Repräsentation, weshalb einheitlich die Darstellung \verb|<fct>| gewählt wird.

Da Consize nur für Wörter eine Repräsentation kennt, müssen die Repräsentationen für die zusammengesetzten Datentypen aus Einzelwörtern mit \verb|word| zu einem Repräsentationswort zusammengesetzt werden. Selbstverständlich ist der Prozess rekursiv.

\begin{verbatim}
>> : repr ( itm -- wrd ) 
>>   dup type
>>   { \ wrd [ ]
>>     \ stk [ [ ] \ [ push <space> push swap 
>>             [ repr push <space> push ] each
>>             \ ] push reverse word ]
>>     \ map [ unmap [ ] \ { push <space> push swap
>>             [ repr push <space> push ] each
>>             \ } push reverse word ]
>>     \ fct [ drop \ <fct> ]
>>     \ nil [ drop \ nil ]
>>     :else [ \ repr-error [ unknown type ] _|_ ]
>>   } case ;
\end{verbatim}
%>> 

Die Repräsentation eines Stapels hat immer eine öffnende und eine schließende Klammer. Sollen die äußeren eckigen Klammern samt der Leer\-räu\-me entfernt werden, so hilft \verb|unbracket-stk-repr|. Ein leerer Stapel wird nach Entfernung der Klammern auf ein Leerzeichen reduziert.

\begin{verbatim}
>> : unbracket-stk-repr ( wrd -- wrd' ) % '[ ... ]' => '...'
>>   unword
>>     pop pop reverse pop pop reverse
>>     dup empty? [ <space> push ] when
>>   word ;
\end{verbatim}
%>> 

In der Einführung zu Consize, genauer in Kap.~\ref{Sec:DataCallStack}, haben wir für die Darstellung einer Continuation, also der gleichzeitigen Darstellung von Data- und Callstack eine Notation vereinbart, in der ein senkrechter Strich "`\verb!|!"' beide Stapel voneinander trennt. Das Wort \verb|printcc| gibt eine Continuation genau so auf der Konsole aus.

\begin{verbatim}  
>> : printcc ( ds cs -- ds cs )
>>   swap dup reverse repr unbracket-stk-repr print
>>   <space> print \ | print <space> print
>>   swap dup repr unbracket-stk-repr println ;
\end{verbatim}
%>> 
  
\begin{verbatim}
> clear [ 2 1 ] [ swap drop ] printcc
1 2 | swap drop
[ 2 1 ] [ swap drop ]
\end{verbatim}

Beachten Sie: Bei der Stapelnotation mit eckigen Klammern liegt das offene Stapelende immer links. Bei der Ausgabe der Continuation ist der Datastack mit seinem offenen Stapelende zum senkrechten Strich hin orientiert. Die Umkehrung in der Darstellung des Datastacks erledigt ein \verb|reverse| in \verb|printcc|.

\subsection{Die REPL: Die Interaktion über die Konsole}

\href{http://de.wikipedia.org/wiki/Lisp}{Lisp} gilt als die zweitälteste Programmiersprache nach Fortran. Mit Lisp kam die \href{http://en.wikipedia.org/wiki/Read\%E2\%80\%93eval\%E2\%80\%93print_loop}{\emph{Read-Evaluate-Print-Loop}} in die Welt. Die REPL beschreibt die Interaktion des Programmierers bzw. der Programmiererin mit Lisp über die Konsole: Die Eingabe wird eingelesen (\emph{read}), der eingegebene Ausdruck ausgewertet (\emph{evaluate}) und das Ergebnis der Auswertung auf der Konsole ausgegeben (\emph{print}). Dieses Schema wiederholt sich wieder und wieder -- das ist die Schleife (\emph{loop}) der Interaktion.

Die REPL beschreibt das universelle Ablaufschema aller interaktiven Sprachen, zu denen Python, Ruby, Perl und eben auch Consize gehören.

Der \verb|reader| macht über das "`\verb|>|"'-Zeichen (samt Leerzeichen) auf sich aufmerksam, nimmt per \verb|read-line| eine Eingabe entgegen, entfernt aus der Eingabe per \verb|uncomment| die Kommentare und aktiviert den Tokenizer mit \verb|tokenize|. Das Resultat ist eine Quotierung auf dem Datastack. Damit \verb|uncomment| funktioniert, muss ein \verb|\newline| \verb|char| zur eingelesenen Eingabezeile hinzugefügt werden.

%>> % INTERACTIVITY
%>> 
\begin{verbatim}  
>> : reader ( -- quot )
>>   \ > print <space> print flush read-line
>>   [ ] \newline char push swapu word
>>   uncomment tokenize ;
\end{verbatim}
%>> 

Der \verb|evaluator| ist gleichzusetzen mit \verb|call| in Consize. 

\begin{verbatim}  
>> : evaluator call ;
\end{verbatim}
%>> 

Der \verb|printer| gibt das Ergebnis der Evaluation, den Datastack, auf der Konsole aus.

\begin{verbatim}
>> : printer ( -- )
>>   get-ds reverse repr unbracket-stk-repr println ;
\end{verbatim}
%>> 

Die \verb|repl| ist die sich wiederholende Abfolge von \verb|reader|, \verb|evaluator| und \verb|printer|.

\begin{verbatim}  
>> : repl reader evaluator printer repl ;
\end{verbatim}
%>> 

So einfach ist es, eine Programmiersprache mit einer REPL zu versehen! Allerdings muss eine interaktive Programmiersprache eine Voraussetzung erfüllen: Kurze syntaktische Einheiten müssen gültige Programme darstellen und inkrementell den Programmzustand verändern können. 
%\footnote{\url{http://denkspuren.blogspot.de/2010/01/scripting-languages.html}}
Beide Belange erfüllt Consize. Traditionelle Compilersprachen wie Java, C, C++ und C\#\ sind allein schon von ihrer Grammatik nicht darauf ausgelegt, "`Kleinstprogramme"' zuzulassen.

\subsection{Dateien lesen und starten}
\label{Sec:Dateien}

% ACHTUNG: Kommentare beginnen mit einem '%'-Zeichen und ignorieren ab
% da an bis zum Zeilenumbruch jeglichen Text. Das heißt: Wörter, die mit
% einem Prozentzeichen beginnen, sind tabu. Das ist sehr strikt.
% Kompatibel mit Consize wäre es, das '%'-Zeichen als Einzelwort (mit
% folgendem Space falls nicht sofort ein Zeilenumbruch folgt) für
% Kommentare zu betrachen. XXX Überdenken!
%
% Man könnte 'uncomment' als Argument ein Wort übergeben,
% das den Anfang eines Kommentars ausweist. Entsprechend
% könnte 'undocument' per Argument flexibler sein und es
% erlauben, mehrere Aspekte aus dem Quellcode zu extrahieren.

Das Laden eines Consize-Programms erfordert nach dem Einlesen (\verb|slurp|) die Entfernung aller Kommentare (\verb|uncomment|) und das auf das Tokenizing reduzierte Parsen des Quelltextes. Das Wort \verb|run| ruft das geladene Programm auf.

Mit \verb|lload| und \verb|lrun| gibt es die entsprechenden Wörter, wenn das Consize-Programm als "`literarisches Programm"' (\emph{literate program}, siehe Kap.~\ref{Sec:Parsing}), vorliegt.

%>> % READING FILES
%>> 
\begin{verbatim}
>> : load ( wrd -- quot ) slurp uncomment tokenize ;
>> : lload ( wrd -- quot ) slurp undocument uncomment tokenize ;
>> : run ( wrd -- ... ) load call ;
>> : lrun ( wrd -- ... ) lload call ;
\end{verbatim}
%>> 

Die folgenden drei Wörter sind nicht viel mehr als Abkürzungen, die bei der (Weiter-)Entwicklung der Prelude von Nutzen sind.

\begin{verbatim}
>> : prelude ( -- ... ) \ prelude.txt run ;
>> : test-prelude ( -- ... ) \ prelude.tests.txt run ;
>> : pprelude ( -- ... ) \ prelude-plain.txt run ;
\end{verbatim}
%>> 

\subsection{Reflexion und Debugging}

Consize ist ein \href{http://de.wikipedia.org/wiki/Reflexion\_(Programmierung)}{reflexives Programmiersystem}, d.h. es kann auf seinen aktuellen Programmzustand zugreifen und ihn verändern; manchmal spricht man auch von \href{http://de.wikipedia.org/wiki/Reflexion\_(Programmierung)}{Introspektion}. Die Fähigkeit dazu ist in der Consize-VM in dem Wort \verb|stepcc| angelegt. Der Programmzustand ist gegeben durch das Wörterbuch, den Data- und den Callstack.

Die folgenden Wörter vereinfachen den Zugriff auf den aktuellen Programmzustand: \verb|lookup| schlägt die mit einem Wort im Wörterbuch assoziierte Quotierung nach, \verb|source| gibt sie auf der Konsole aus. Das Wort \verb|get-ds| legt den Datastack auf dem Datastack ab (was seltsam klingen mag, aber funktioniert), \verb|set-ds| verändert den Datastack und mit \verb|clear| kann der Datastack "`gelöscht"' werden.

%>> % REFLECTION & DEBUGGING
%>> 
\begin{verbatim}
>> : lookup ( word -- item ) get-dict \ word-not-found get ;  
>> : source ( word -- ) lookup repr println ;
\end{verbatim}
%>> 

\begin{verbatim}
>> : get-ds ( -- stk ) [ swap dup push swap continue ] call/cc ;
>> : set-ds ( stk -- ) [ swap top swap continue ] call/cc ;
>> : clear ( -- ) [ ] set-ds ;
\end{verbatim}
%>> 

Das Wort \verb|abort| unterbricht die Programmausführung und bietet die REPL zur Interaktion an. Das Wort \verb|exit| beendet die Arbeit der Consize-VM. Sobald der Callstack gänzlich abgearbeitet, d.h. leer ist, hat die Consize-VM ihre Aufgabe erfüllt. 

\begin{verbatim}
>> : abort ( -- ) [ drop [ printer repl ] continue ] call/cc ;
>> : exit  ( -- ) [ drop [ ] continue ] call/cc ;
\end{verbatim}
%>> 

In den \href{http://de.wikipedia.org/wiki/Computer#Entwicklung\_des\_modernen\_turingm.C3.A4chtigen\_Computers}{Urzeiten der Computerei} bestanden die Rechner teils aus elektromechanischen \href{http://de.wikipedia.org/wiki/Relais}{Relais} und teils aus rein elektronischen Bauteilen wie \href{http://de.wikipedia.org/wiki/Elektronenr\%C3\%B6hre}{Röhren}. Sie dürfen sich diese Bauteile in den Größendimensionen eines Daumens und größer vorstellen. Die damaligen Rechner beanspruchten mit ihren mehreren Tausend Bauteilen nicht nur den Platz ganzer Schränke, sondern den ganzer Räume. So soll einst ein Käfer, zu Englisch \emph{bug}, eine Fehlfunktion ausgelöst haben, als er in den Wirrungen des elektronischen Allerleis herumkrabbelte, einen Kurzschluss auslöste und sein Leben ließ. Seit diesem historisch dokumentierten Ereignis werden auch die \href{http://de.wikipedia.org/wiki/Programmfehler}{Programmfehler} in der Software als "`Bugs"' bezeichnet.

Seinerzeit gestaltete sich die Suche nach einem verkohlten Käfer in den unendlichen Weiten der Hardware als Herausforderung. Mit der Erfindung des \href{http://de.wikipedia.org/wiki/Integrierter\_Schaltkreis}{Integrierten Schaltkreises} (\emph{integrated circuit}, IC) und der darauf folgenden drastischen Miniaturisierung der Hardware, gehört diese Art der Fehlersuche der Vergangenheit an. Doch nicht minder schwer und aufwendig ist bisweilen die Suche nach den meist unfreiwillig eingebauten "`Bugs"' in der Software.

Die Suche nach dem Softwarefehler nennt man "`Debugging"' und das dazu verwendete Hilfsmittel als "`\href{http://de.wikipedia.org/wiki/Debugger}{Debugger}"'. Eine zentrale Funktion eines Debuggers ist die Einzelschritt-Ausführung eines Programm ab einem definierten \href{http://de.wikipedia.org/wiki/Debugger#Haltepunkte}{Haltepunkt}, dem \emph{breakpoint}. So kann man sozusagen in Zeitlupe, Schritt für Schritt verfolgen, was das Programm tut und zwischen den Einzelschritten den aktuellen Programmzustand inspizieren. All das soll helfen, einen Softwarefehler systematisch einzukreisen und zu entdecken. 

Das Wort \verb|break| definiert einen Haltepunkt. Das Wort legt die aktuelle Continuation auf dem Datastack ab und bietet dazu den gewohnten interaktiven Dialog an.

\begin{verbatim}
>> : break ( -- ds cs ) [ printer repl ] call/cc ;
\end{verbatim}
%>> 

Das Wort \verb|step| führt einen Rechenschritt mit der auf dem Datastack befindlichen Continuation aus.

\begin{verbatim}
>> : step ( ds cs -- ds' cs' )
>>   dup empty? [ get-dict -rot stepcc rot drop ] unless ;
\end{verbatim}
%>> 

Um das oberste Wort auf dem Callstack der Continuation komplett auszuführen, dazu dient \verb|bstep| (\emph{big step}). Das Wort funktioniert nur, wenn die weiteren Wörter auf dem Callstack keine Rolle spielen -- was der Normalfall ist.

\begin{verbatim}
>> : bstep ( ds cs -- ds' cs' )
>>   unpush dup
>>   { \ \   [ drop unpush [ ] swapu \ \ push ]
>>     :else [ [ ] swapu ]
>>     nil   [ drop [ ] ]
>>   } case get-dict func swap [ apply ] dip ;
\end{verbatim}
%>> 

Ersetzt man im Beispiel \verb|bstep| durch \verb|step|, tritt der Unterschied in der Auflösung der Programmausführung deutlich zutage.

\begin{verbatim}
> clear [ 2 3 ] [ \ 4 -rot + ]
[ 2 3 ] [ \ 4 -rot + ]
> bstep
[ 4 2 3 ] [ -rot + ]
> bstep
[ 2 3 4 ] [ + ]
> bstep
[ 5 4 ] [ ]
> bstep
[ 5 4 ] [ ]
\end{verbatim}

\subsection{Unit-Testing}

Der \href{http://de.wikipedia.org/wiki/Softwaretest}{Softwaretest} ist eine qualitätssichernde Maßnahme und gerade auf der Modulebene so wichtig, dass eine Unterstützung zur Formulierung und Ausführung von \href{http://de.wikipedia.org/wiki/Modultest}{Modultests} (\emph{unit tests}) nicht fehlen soll. Für praktisch jede Programmiersprache wird für diesen Zweck eine \href{http://de.wikipedia.org/wiki/Liste\_von\_Modultest-Software}{Unittest-Soft\-ware} bereitgestellt, die das Testen vereinfacht. In Consize ist so etwas in zwei Zeilen Code programmiert, wenn man auf die Ausgabe auf der Konsole verzichtet. Mit Konsolen-Ausgaben braucht es ein paar Zeilen mehr.

%>> % UNIT-TESTING
%>> 
\begin{verbatim}
>> : unit-test ( result quot -- )
>>   [ \ test print [ <space> print repr print ] bi@ ] 2keep 
>>   [ fcall equal? ] 2keep
>>   rot
>>     [ <space> print \ passed println 2drop ]
>>     [ <space> print \ failed println \ with print <space> print
>>       nip fcall repr println abort ]
>>   if ;
\end{verbatim}
%>> 

Ein Unittest erwartet den zu antizipierten Inhalt des Datastacks (\verb|result|) nach Abarbeitung des in \verb|quot| abgelegten Programms. Produziert der Aufruf von \verb|quot| nicht das mit \verb|result| vorgegebene Resultat, bricht die Ausführung ab und das erwartete Ergebnis wird zusammen mit der Abbruchmeldung ausgegeben. Die Angabe des erwarteten Ergebnisses hilft, den Fehlschlag des Tests besser zu verstehen.

\begin{verbatim}
> ( 5 ) [ 2 3 + ] unit-test
test [ 5 ] [ 2 3 + ] passed

> ( 7 ) [ 2 3 + ] unit-test
test [ 7 ] [ 2 3 + ] failed
with [ 5 ]
\end{verbatim}

\section{Serialisierung, Consize-Dumps und Bootstrapping}

\subsection{Die Serialisierung von Daten}

Mit der \href{http://en.wikipedia.org/wiki/Serialization}{Serialisierung} eines Datums ist eine Beschreibungsform gemeint, die zur sequentiellen Ablage auf einem Datenträger zwecks Speicherung geeignet ist und eine vollständige Rekonstruktion des Datums erlaubt.

Consize serialisiert Daten so, wie Sie es in der Einleitung zu Consize in Kap.~\ref{Sec:Datenstrukturen} (S.\pageref{Sec:Datenstrukturen}ff.) kennengelernt haben. Das Wort \verb|serialize| automatisiert den Vorgang, ein Datum einzig mit den Wörtern der Consize-VM in eine Wortfolge zur Erzeugung des Datums zu übersetzen.

%>> % SERIALIZATION & DUMPING
%>> 
% Die Serialisierung ist eine besondere Form der Repräsentation (Kodierung)
\begin{verbatim}
>> : serialize ( quot -- quot' )
>>   get-ds [ clear ] dip
>>   dup top swap pop     
>>   [ -serialize- get-ds ] dip
>>   swap reverse push set-ds ;
\end{verbatim}
%>> 

\begin{verbatim}  
>> : -serialize- ( item -- stream-of-items )
>>   dup type
>>   { \ wrd [ \ \ swap ] 
>>     \ stk [ \ emptystack swap reverse [ -serialize- \ push ] each ]
>>     \ map [ unmap -serialize- \ mapping ]
>>     \ nil [ drop \ emptystack \ top ]
>>     :else [ \ serialization-error [ invalid type ] _|_ ]
>>   } case ;
\end{verbatim}
%>> 

Mit \verb|call| können serialisierte Daten wieder rekonstruiert werden.

\begin{verbatim}
> clear [ 1 hello 2 ] serialize
[ emptystack \ 2 push \ hello push \ 1 push ]
> call
[ 1 hello 2 ]
\end{verbatim}

Die Wörter \verb|remove-fct-assocs| und \verb|keep-fct-assocs| sind zwei Hilfs\-wör\-ter: Sie entfernen (\emph{remove}) oder behalten (\emph{keep}) die Einträge in einem Wörterbuch, die mit einer Funktion assoziiert sind. Mit diesen Wörtern wird das Erzeugen eines Dumps vereinfacht!

\begin{verbatim}  
>> : remove-fct-assocs ( dict -- dict' )
>>   dup keys
>>   [ 2dup swap \ _|_ get
>>     type \ fct equal?
>>       [ swap dissoc ]
>>       [ drop ]
>>     if ] each ;
\end{verbatim}
%>> 

\begin{verbatim}    
>> : keep-fct-assocs ( dict -- dict' )
>>   dup keys
>>   [ 2dup swap \ _|_ get
>>     type \ fct equal?
>>       [ drop ]
>>       [ swap dissoc ]
>>     if ] each ;
\end{verbatim}
%>> 

\subsection{Der Dump: Ein Schnappschuss des Wörterbuchs}

Der \verb|dump| erzeugt eine speicherfähige Kopie des Gedächtnisses von Consize einschließlich der übergebenen Quotierung. Das zentrale Gedächtnis von Consize ist das Wörterbuch.

Zur Erzeugung des Dumps müssen alle atomaren Wörter der Consize-VM aus dem Wörterbuch entfernt werden, da die mit ihnen assoziierten Funktionen nicht serialisierbar sind -- das ist auch gar nicht nötig, da die grundlegenden Wörter der Consize-VM und ihre Funktionen ohnehin zur Verfügung stehen. Die mit \verb|dump| übergebene Quotierung dient als Startroutine, so dass ein Dump, der z.B. von einem Speichermedium eingelesen wird, sich selbst aktivieren und starten kann.

% Dump nutzt Serialisierung als Kodierung für schnelles Einlesen
% Plain-Prelude nutzt syntaktische Kodierung für programmierfreundl.
% Darstellung

\begin{verbatim}
>> : dump ( quot -- quot' )
>>   [ ] get-dict remove-fct-assocs push serialize
>>   swap serialize concat
>>   [ continue ] concat ;
\end{verbatim}
%>> 

Mit \verb|create-dump| wird ein Dump unter dem angegebenen Namen im Dateisystem abgelegt, der von der Consize-VM gestartet werden kann und sich nach dem Start mit \verb|say-hi| und \verb|repl| über die Konsole meldet. Seien Sie übrigens ein wenig geduldig, das Erzeugen eines Dumps nimmt etwas Zeit in Anspruch.

\begin{verbatim}    
>> : create-dump ( filename -- )
>>   [ get-dict swap merge set-dict say-hi repl ] dump
>>   repr unbracket-stk-repr swap spit ;
\end{verbatim}
%>>   

Wozu ist ein Dump von Consize überhaupt von Nutzen?

Die Version der Prelude, die Sie aktuell lesen, ist die Prelude im Klartext. Diese Fassung der Prelude verwendet die in Kap.~\ref{Sec:Grammatik+} vorgestellten Erweiterungen für eine programmierfreundliche Darstellung des Quelltextes. Mit dieser Darstellung geht nur ein kleines Problem einher: Das Einlesen der Prelude dauert ein wenig, da das inkrementelle Definieren von Wörtern und das Auflösen syntaktischer Kodierungen etwas Zeit benötigt. Viel effizienter ist es, einen mit \verb|create-dump| erzeugten Dump der Prelude einzulesen. Darum startet die Consize-VM in aller Regel mit einem Dump der Prelude.

Sie können also Consize sowohl mit dem Dump der Prelude oder mit der Klartext-Prelude starten. Da Consize beim Start generell die Datei \verb|prelude.txt| erwartet, ist entweder die Dump- oder die Klartext-Datei entsprechend umzubenennen. In der Regel ist die Datei \verb|prelude.txt| die Dump-Version und \verb|prelude-plain.txt| die Prelude im Klartext. Die Datei \verb|prelude.txt| kann man auch mit dem Wort \verb|prelude| laden und starten. Analog lädt und startet \verb|pprelude| die Datei \verb|prelude-plain.txt|, siehe Kap.~\ref{Sec:Dateien}.

\subsection{Bootstrapping Consize}
\label{Sec:Bootstrapping}

Um Consize mit einem Dump der Prelude starten zu können, muss der Dump erst einmal erzeugt werden. Dazu ist es notwendig, Consize mit der Prelude im Klartext zu starten. Die Klartext-Fassung der Prelude kann von der Consize-VM nicht so ohne weiteres verarbeitet werden. Schließlich verwendet die Prelude Erweiterungen (siehe Kap.~\ref{Sec:Grammatik+}), die Consize zu Beginn nicht kennt.

Das ist der Grund, warum die Prelude mit dem Laden des sogenannten Bootimage beginnt (siehe Kap.~\ref{Sec:LoadBootimage}). Das Bootimage ist ein Programm, das all die Wörter definiert, die notwendig sind, um die Verarbeitung der Prelude mit ihren syntaktischen Erweiterungen vorzubereiten. Das Bootimage muss dazu freilich selber auf diese Erweiterungen verzichten, weshalb es nicht sonderlich leserlich daherkommt.

Ursprünglich habe ich das Bootimage per Hand geschrieben, und anfangs gab es auch keine gesonderte Datei mit dem Bootimage, die notwendigen Definitionen waren direkter Bestandteil der Prelude. Inzwischen nimmt mir das Wort \verb|bootimage| die Handarbeit ab. Es produziert automatisch den Code für die einleitenden Definitionen und speichert sie in der Datei \verb|bootimage.txt| ab.

%>> % BOOTSTRAPPING
%>> 
\begin{verbatim}        
>> : bootimage ( -- )
>>   bootstrap repr unbracket-stk-repr \ bootimage.txt spit ;
\end{verbatim}
%>> 

Dieser Automatismus verschleiert ein wenig, wie das Bootimage historisch entstand, welche "`Handarbeit"' nötig war, um die Verarbeitung der Prelude mit den Literalen für Stapel und Mappings und mit der Notation für Definitionen zu ermöglichen. Um den Weg nachvollziehbar zu machen, sei hier der Ausgangspunkt des Bootimages, die Entstehung des Wortes \verb|def| ausführlich beschrieben.

Das Wort \verb|def| ist essentiell. Es steht im Brennpunkt aller weiterer Aktivitäten, die immer darauf abzielen, neue Wörter dem Wörterbuch hinzuzufügen. Aus Kap.~\ref{Sec:DefWords} kennen Sie die Definition:

\begin{verbatim}
: def ( wrd itm -- ) swap get-dict assoc set-dict ;
\end{verbatim}

Zu Beginn steht uns diese Schreibweise in Consize nicht zur Verfügung. Beim Start von Consize sind ausschließlich die Wörter der Consize-VM verfügbar. Wir müssen uns den gewünschten Programmierkomfort Schritt für Schritt "`erarbeiten"'.

Angenommen, das Wort \verb|def| wäre in Consize bereits definiert, dann könnten wir \verb|def| immerhin mit sich selbst definieren.

\begin{verbatim}
\ def [ swap get-dict assoc set-dict ] def
\end{verbatim}

Aber wie kann ein Wort sich selbst definieren ohne bereits definiert zu sein? Natürlich geht das nicht. Aber der Zirkelschluss, dass sich ein Wort selbst definiert, lässt sich händisch auflösen. Informatiker nennen diese Technik "`\href{http://de.wikipedia.org/wiki/Bootstrapping\_(Informatik)}{Bootstrapping}"'. Wir ersetzen einfach \verb|def| mit seiner eigenen Definition!

\begin{verbatim}
\ def [ swap get-dict assoc set-dict ] swap get-dict assoc set-dict
\end{verbatim}

Noch steht uns allerdings eines im Weg. Am Anfang der Prelude können wir nicht die Notation mit den eckigen Klammern nutzen. Wir müssen die Quotierung ebenfalls händisch aufbauen.

\begin{verbatim}
\ def
emptystack \ set-dict push \ assoc push \ get-dict push \ swap push
swap get-dict assoc set-dict
\end{verbatim}

Das ist exakt der Code, den Consize in den ersten zwei Zeilen des Wortes \verb|bootstrap| erzeugt, um ein Bootimage zu erstellen.

\begin{verbatim}
>> : bootstrap ( -- quot )
>>   [ \ def ] \ def lookup serialize concat 
>>     \ def lookup concat
>>   [ swapu *effect* def+ unpush -rot over
>>     SYMBOL: case when if choose call t f false fcall lookup
>>     scan4] scan4[ parse-quot destruct-definition
>>     : scan4; look4)
>>     read-word read-mapping ]
>>   ( \ [ \ ( \ { ) concat
>>   [ bootstrap-word concat ] each ;
\end{verbatim}
%>> 

Probieren Sie es an der Konsole aus! Ich habe mir hier aus Platzgründen lediglich erlaubt, die Ausgabe an der Konsole durch Zeilenumbrüche ein wenig lesbarer zu machen.

\begin{verbatim}
> clear

> [ \ def ] \ def lookup serialize concat
[ \ def emptystack \ set-dict push \ assoc push
                   \ get-dict push \ swap push ]
> \ def lookup concat
[ \ def emptystack \ set-dict push \ assoc push
                   \ get-dict push \ swap push
swap get-dict assoc set-dict ]
\end{verbatim}

Jetzt, da \verb|def| definiert ist, kann man damit alle weiteren Wörter aus Kap.~\ref{Sec:DefWords} definieren wie z.B. \verb|*effect*|, \verb|def+| und zuvor \verb|swapu|, da \verb|swapu| in der Definition von \verb|def+| verwendet wird. Das Wort \verb|bootstrap-word| automatisiert die Arbeit, die ich einst händisch erledigen musste.

\begin{verbatim}
>> : bootstrap-word ( wrd -- quot )
>>   [ [ ] swapu \ \ push ] keep
>>   lookup serialize concat
>>   [ def ] concat ;
\end{verbatim}
%>> 

Den Code zur Definition von \verb|swapu| generiert \verb|bootstrap-word| wie folgt; per Hand habe ich seinerzeit (ohne die umgebenden eckigen Klammern) exakt diesen Code geschrieben.

\begin{verbatim}
> clear \ swapu bootstrap-word
[ \ swapu emptystack \ push push \ swap push def ]
\end{verbatim}

Die Auswahl der zum Bootstrapping benötigten Wörter, ihre Ab\-hän\-gig\-kei\-ten und die Reihenfolge der Definitionen dokumentiert der Definitionsrumpf des Wortes \verb|bootstrap|.

Ist dieser Prozess des händischen Schreibens von vorbereitenden Wortdefinitionen einmal geschehen, dann kann die Prelude geladen, ein Dump produziert und der händische Vorbereitungsteil verworfen werden. Fortan können über den Dump Änderungen an der Klartext-Prelude geladen und zu einem neuen Dump aufbereitet werden. Plötzlich ist nicht mehr erkenntlich, was zuerst da war: der Dump oder die Prelude im Klartext.

Das ist schon kurios und erinnert sehr an das \href{http://de.wikipedia.org/wiki/Henne-Ei-Problem}{Henne/Ei-Problem}. Was war zuerst da: die Henne oder das Ei? Ohne Huhn kein Ei und ohne Ei kein Huhn. Oder am Beispiel von \verb|def| noch extremer: Ohne \verb|def| kein \verb|def|. Wir Informatiker halten uns nicht lange mit solchen philosophisch anmutenden Fragestellungen auf und durchbrechen per Bootstrapping die Selbstbezüglichkeit. Das Ergebnis: Sie haben den Kreislauf von Huhn und Ei in Gang gesetzt. Auf eben diese Weise haben wir das Wort \verb|def| aus der Taufe gehoben, um die restlichen Wörter zu definieren. Sie können nun auch \verb|def| mit sich selber definieren.
Und ist das einmal geschehen, können Sie kess die Frage nach dem "`Was war zuerst?"' stellen.\footnote{Sie dürfen davon ausgehen, dass Hühner nicht per Bootstrapping entstanden sind ;-)}

Um den Bootstrapping-Prozess nicht vollkommen zu vernebeln, ist das Wort \verb|bootstrap| in die Prelude aufgenommen worden, die den historischen Vorgang des händischen Bootstraps zwar nicht exakt nachbildet, aber von seiner Idee her dokumentiert. Prinzipiell könnte auch ein Mini-Dump mit den Wörtern aus \verb|bootstrap| zum Start der Prelude herangezogen werden, damit wäre aber die Idee des Bootstrappings nicht mehr nachvollziehbar.

Die Prelude definiert auch noch einmal all die Wörter, die durch das Bootimage bereits definiert sind. Das geschieht vor allem zu Dokumentationszwecken. Die Wortdefinitionen im Bootimage kennen beispielsweise keine Angabe von Stapeleffekten. Das wird mit der Prelude nachgeholt. Die Prelude überschreibt sozusagen die Definition der Wörter aus dem Bootimage.

\section{Here we go!}

\subsection{Consize meldet sich zur Arbeit}

Die Prelude begrüßt mit \verb|say-hi| den Anwender bzw.\ die Anwenderin und startet die REPL. Nun ist Consize zur Interaktion bereit!

%>> % HERE WE GO
%>> 
\begin{verbatim}
>> : say-hi ( -- )
>>   [ ]
>>   [ This is Consize -- A Concatenative Programming Language ]
>>   [ push <space> push ] each
>>   pop reverse word println ;
\end{verbatim}
%>> 

\begin{verbatim}
>> say-hi repl
\end{verbatim}
%>> 

\subsection{Von der Dokumentation zum Code}

Die Dokumentation zur Prelude, die Sie gerade lesen, enthält den voll\-stän\-di\-gen Code zur Prelude; das sind all die Textstellen, die mit "`\verb|>> |"' ausgewiesen sind. Dieses Dokument ist also selbst ein Beispiel für ein "`literarisches Programm"'. Sie können den Quellcode der Prelude aus der Dokumentation mit dem folgendem Programm aus dem \href{http://de.wikipedia.org/wiki/LaTeX}{\LaTeX}-File extrahieren und unter einem neuen Dateinamen abspeichern.

\begin{verbatim}
> \ Consize.Prelude.tex slurp undocumment \ <filename> spit
\end{verbatim}

Achten Sie darauf, dass Sie sich nicht ungewollt die Datei mit der aktuellen Prelude überschreiben.


